Compare commits

...

420 commits

Author SHA1 Message Date
Nicolas Leger
c5f69e3f64 chore(ngdoc): fix misspellling of Naturally in sortVersionsNatrually
Corrects "sortVersionsNatrually" method name in `ngdoc.js` in "sortVersionsNaturally"
2014-02-04 16:43:39 -08:00
Daniel Luxemburg
dd24c78373 fix(ngMock): return false from mock $interval.cancel() when no argument is supplied
Closes #6103.
Closed #6099.
2014-02-04 16:41:25 -08:00
Caitlin Potter
36d37c0e38 fix(jqLite): trim HTML string in jqLite constructor
jQuery will construct DOM nodes containing leading whitespace. Prior to this change, jqLite would
throw a nosel minErr due to the first character of the string not being '<'. This change corrects
this behaviour by trimming the element string in jqLite constructor before testing for '<'.

Closes #6053
2014-02-04 16:39:52 -08:00
Caitlin Potter
24699ee8f0 fix($http): ignore xhr.responseType setter exception if value is "json"
WebKit added support for the json responseType value on 09/03/2013
https://bugs.webkit.org/show_bug.cgi?id=73648. Versions of Safari prior to 7 are known to throw when
setting the value "json" as the response type. Other older browsers implementing the responseType.
Other browsers with infrequent update cycles may also be affected.

The json responseType value can be ignored if not supported, because JSON payloads are parsed on the
client-side regardless.

Closes #6115
Closes #6122
2014-02-04 19:34:31 -05:00
GiffenGood
aa6a0e3fc6 docs(log.js): param debugEnabled is a boolean and not a string 2014-02-04 16:26:36 -08:00
Tobias Bosch
8761ddc0e3 chore(release): be able to release any commit
The version information is now stored only in the tags.
By this we are able to release commits in the past, which
have already been tested, so we don't need a code freeze
or run tests any more. This is also the first step for
letting Travis do the releases in the future.

The package.json now contains the new
property 'branchVersion' that defines which tags are
valid on this branch.

Closes #6116
2014-02-04 16:20:22 -08:00
Caitlin Potter
058842ad04 revert: "fix($http): ignore xhr.responseType setter exception if value is "json""
This reverts commit 431bad0183.
2014-02-04 19:09:53 -05:00
Caitlin Potter
431bad0183 fix($http): ignore xhr.responseType setter exception if value is "json"
WebKit added support for the json responseType value on 09/03/2013
https://bugs.webkit.org/show_bug.cgi?id=73648. Versions of Safari prior to 7 are known to throw when
setting the value "json" as the response type. Other older browsers implementing the responseType.
Other browsers with infrequent update cycles may also be affected.

The json responseType value can be ignored if not supported, because JSON payloads are parsed on the
client-side regardless.

Closes #6115
Closes #6122
2014-02-04 18:46:54 -05:00
Caitlin Potter
5850e61c82 docs(CHANGELOG): add breaking change notice for 1.2.9 $http default headers change
Add a mention for the slightly breaking change introduced in 1.2.9.

Closes #6022
2014-02-04 10:59:44 -05:00
Thomas Belin
d2e4e49986 fix(ngResource): don't filter "$"-prefixed properties from ngResource requests/responses
ngResource no longer filters properties prefixed with a single "$" character from requests or
responses, correcting a regression introduced in 1.2.6 (cb29632a) which caused shallowCopy and
shallowClearAndCopy to ignore properties prefixed with a single "$".

Closes #5666
Closes #6080
Closes #6033
2014-02-04 10:51:24 -05:00
Kamil Pekala
0da6cc9118 docs($compile): fixed syntax error.
"how to" was written twice in a row.

Closes #6110
2014-02-04 08:45:48 -05:00
John Kurlak
cc60ba1f35 docs($q): fixed grammatical error
"Promises" should be of the possessive form.

Closes #6082
2014-02-04 00:00:31 -08:00
Igor Minar
64d58a5b52 refactor(mocks): simplify the implementation 2014-02-03 22:41:18 -08:00
Wes Alvaro
3bf4390339 fix(mocks): always call functions injected with inject with this set to the current spec
Currently when a function is injected inside of a test we set the context to undefined which
is a bug.

Closes #6102
2014-02-03 22:25:30 -08:00
gdi2290
e7ac7aa43b chore(Gruntfile.js, package.json): use load-grunt-tasks and move grunt-contrib-jshint into devDependencies
Closes #6085
2014-02-03 19:25:47 -05:00
PatrickJS
37781ed145 style(License): update copyright year
Closes #6090
2014-02-03 19:19:29 -05:00
Igor Minar
19ba6510d0 chore(ngClass): remove debugger statement from an e2e test 2014-02-03 11:43:14 -08:00
jenkins
bc5ceee275 chore(release): update cdn version 2014-02-03 10:03:06 -08:00
jenkins
106af49258 chore(release): start v1.2.12 (1.2.12) 2014-02-03 09:41:17 -08:00
jenkins
d5eedf38db chore(release): cut v1.2.11 release 2014-02-03 09:40:03 -08:00
Tobias Bosch
c0c0b2b674 docs(changelog): release notes for 1.2.11 2014-02-03 09:28:45 -08:00
Caitlin Potter
ce1f1f97f0 fix(ngResource): don't append number to '$' in url param value when encoding URI
Previously, if a URL parameter value included a $, it would replace the dollar sign with a literal
'$1' for mysterious reasons. Using a function rather than a replacement string circumvents this
behaviour and produces a more expected result.

Closes #6003
Closes #6004
2014-02-03 11:12:07 -05:00
Alan Rubin
8205158e47 docs(animations): ngClass usage should link to ngClass documentation
Fixing reference to ngClass documentation

Closes #6089
2014-02-03 09:14:45 -05:00
Igor Minar
6609e3da76 fix(http): make jshint happy 2014-01-31 17:03:30 -08:00
Jorg
ef210e5e11 fix($http): update httpBackend to use ActiveXObject on IE8 if necessary
window.XMLHttpRequest is not always available in IE8 despite it not running in quirks mode,
in which case Angular should be using the ActiveXObject instead. Just checking the browser
version is taking too many shortcuts.

Closes #5677
Closes #5679
2014-01-31 16:52:42 -08:00
Stéphane Reynaud
fd61e222c3 docs(guide/templates.css-styling): fix "{{}}"
Replace {{}} to `{{}}` so that "{{}}" is rendered in the HTML page

Closes #5950
2014-01-31 16:31:06 -08:00
Lucas Galfasó
074b0675a1 fix($q): make $q.reject support finally and catch
Add support for the functions `finally` and `catch` to the
promise returned by `$q.reject`

Closes #6048
Closes #6076
2014-01-31 14:38:06 -05:00
Caitlin Potter
5ed721b9b5 fix($compile): retain CSS classes added in cloneAttachFn on asynchronous directives
Previously, classes added to asynchronous directive elements during the clone
attach function would not persist after the node is merged with the template, prior
to linking. This change corrects this behaviour and brings it in line with synchronous
directives.

Closes #5439
Closes #5617
2014-01-31 12:45:35 -05:00
Vojta Jina
c22ab5d2e2 chore(travis): remove BrowserStack credentials
Closes #5596
2014-01-31 07:48:36 -08:00
Igor Minar
339a1658cd fix(filterFilter): don't interpret dots in predicate object fields as paths
Closes #6005
Closes #6009
2014-01-31 03:16:46 -08:00
Shawn Flahave
29432ffe37 Edited the 'Flushing HTTP requests' section
Minor grammatical edits in the Flushing HTTP requests section.
2014-01-30 16:52:06 -08:00
Brad Williams
caed2dfe4f fix(docs): clarify doc for "args" in $broadcast and $emit
Closes #6047.
2014-01-30 16:50:08 -08:00
Igor Minar
7f4edaff6e chore(build): add jscs code style check to our build
Closes #6062
2014-01-30 11:39:53 -08:00
Igor Minar
6dcfccb32c chore(grunt): sort the grunt task load statements 2014-01-30 10:51:20 -08:00
Clark Pan
e2173f9101 docs($provide): return instance of Ping, rather than constructor
Updating $provide.service method docs

The previous example provided for the service method did not work.  I've updated the example to a working example.

I think this version of the example will probably make more sense to most people, and the factory method would be
a better place for this sort of example.

Closes #6008
2014-01-29 09:10:01 -05:00
Manan
7a78aed160 docs(compile/nodomevents): fix typo ng-mode -> ng-model
correcting directive name to ng-model instead of ng-mode in nodomevents.ngdoc

Correcting use of ng-model directive

Closes #6036
2014-01-29 08:51:02 -05:00
Julie
7aef2d54e0 test(docs): convert example end to end doc tests from scenario runner to protractor
Thanks to jeffbcross, petebacondarwin, btford, jdeboer, tbosch for contributions!

Closes #6023
2014-01-28 14:14:20 -05:00
Julie
ce37ae2868 docs(cookbook): remove the cookbook docs
The cookbook docs are now superceded by the guide. They are no longer available
in any menus and the only way to find them is to search for them. Remove!

Closes #5967
2014-01-28 14:12:52 -05:00
John Papa
95f0bf9b52 fix(mocks): refactor currentSpec to work w/ Jasmine 2
Closes #5662
2014-01-27 22:26:18 -08:00
Igor Minar
8a0be355a9 docs(triaging.md): update the 'PRs plz!' label name 2014-01-27 21:17:53 -08:00
Igor Minar
849a1489c7 style(triaging.md): removing ws 2014-01-27 12:06:17 -08:00
Brian Ford
f54f0f98a0 chore(docs): remove note about removing disqus 2014-01-27 11:46:18 -08:00
David Nelson
766b3d5c87 docs(select): rephase note on ngOptions
added 'an' and 'the' to ngOptions sentence

Closes #5993
2014-01-26 15:45:04 -05:00
David Nelson
4f735b0605 docs(ngSwitch): fixed typo 'choses' to 'chooses'
Closes #5992
2014-01-26 15:42:27 -05:00
jenkins
319dd1a449 chore(release): update cdn version 2014-01-24 19:27:18 -08:00
jenkins
88a14b4e25 chore(release): start v1.2.11 (1.2.11) 2014-01-24 15:42:49 -08:00
jenkins
451bde1244 chore(release): cut v1.2.10 release 2014-01-24 15:28:28 -08:00
Matias Niemelä
4f827f587b docs(changelog): release notes for 1.2.10 2014-01-24 13:34:45 -05:00
Matias Niemelä
131410b61b docs(search): make sure the forward slash doesn't focus on search while on another input element
Closes #5969
2014-01-24 13:02:50 -05:00
Matias Niemelä
ca6b7d0fa2 feat($animate): provide support for a close callback
Closes #5685
Closes #5053
Closes #4993
2014-01-24 12:21:29 -05:00
Brian Ford
40dc806e03 docs(guide/filter): link to an example of a filter unit test 2014-01-23 13:43:31 -08:00
Peter Bacon Darwin
5e9835b4f2 docs(ngdoc): ensure module installation docs are accurate
The ngMock module is built into a package called angular-mocks, which is
not named consistently and the docs were giving invalid info.

Closes #5810
2014-01-23 17:27:30 +00:00
Caitlin Potter
e0209169bf fix(a): don't preventDefault on click when SVGAElement has an xlink:href attribute
Before this change, an SVGAElement with an xlink:href attribute and no href or name attribute which
was compiled by the angular HTML compiler would never be clickable, due to the htmlAnchorDirective
calling event.preventDefault() due to the missing href attribute.

This change corrects this behaviour by also testing the xlink:href attribute if the element in
question is determined to be an SVG anchor tag (with the href property having type SVGAnimatedString)

Closes #5896
Closes #5897
2014-01-22 14:51:47 -05:00
Martin Probst
b07afa0465 refactor(externs): move Closure Externs back to Closure code repository
While Closure Compiler generally recommends to maintain the externs for
projects together with their source, this has not worked well for
AngularJS:
- Changes to externs must be tested; they can break clients. AngularJS
  has no testing infrastructure for this.
- Changes mostly come from users inside of Google and are much more
  easily submitted together with the code using them within Google's
  repository.

This change deletes the externs here and adds a README.closure.md to
document the change. They will be added back to Closure Compiler in a
separate submit.

Closes #5906
2014-01-22 11:38:14 -08:00
Allon Hadaya
c3b5e16d84 docs(ngRoute): grammar correction
grammar: occurs -> occur

Closes #5937
2014-01-22 14:26:33 -05:00
Igor Minar
7f444a205e style($interval): remove ws and replace comma with semicolon 2014-01-22 11:14:59 -08:00
Julie
82213efff2 test(doc:protractor): turn off animation for doc end to end tests to speed things up 2014-01-22 12:41:35 -05:00
gabrielbrasil
ec59be67bc docs(ngMock): $log.error property contains messages from $log.error, not $log.log
Closes #5932
2014-01-22 11:34:56 -05:00
Caitlin Potter
79e519feda fix(input): use Chromium's email validation regexp
This change uses the regexp from Chromium/Blink to validate emails, and corrects
an error in the validation engine, which previously considered an invalid email
to be valid. Additionally, the regexp was invalidating emails with capital
letters, however this is not the behaviour recomended in the spec, or implemented
in Chromium.

Closes #5899
Closes #5924
2014-01-21 21:40:55 -05:00
matthewhintzen
7cf5544a9f docs(tutorial): update step_12.ngdoc
This time I feel good about this modification to the document, the code listing
on the tutorial page for the animation.js DID NOT match what was actually IN the
file for that branch.  Updated tutorial to reflect actual contents of file

Closes #5922
2014-01-21 17:23:05 -08:00
Narretz
030a9b8d33 docs(changelog): remove reverted commit from 1.2.9
Closes #5868
2014-01-21 17:17:14 -08:00
Igor Minar
310f129c1d docs(guide/directive): clarify attr object definition
Closes #5884
2014-01-21 17:14:00 -08:00
Igor Minar
0fc64ad8a1 style(guide/directive): remove ws 2014-01-21 17:12:34 -08:00
Jan Hancic
12d1f5700d chore(docs): add spacing to tutorial buttons
Added 5px of right margin to tutorial buttons (Previous, Live demom ...).

Closes #5901
2014-01-21 17:04:49 -08:00
Brian Ford
60e80509a8 docs(select): add callout style for a note 2014-01-21 17:02:50 -08:00
Dan Matthews
3c12d36e73 docs(select): add object comparison warning 2014-01-21 16:58:41 -08:00
Caitlin Potter
fd6bac7de5 fix(ngRoute): pipe preceding route param no longer masks ? or * operator
Before this change,

```js
$routeProvider.when('/foo/:bar|?', { ... });
```

would not have the expected effect --- the parameter would not be optional, and
the pipe would not be included in the parameter name.

Following this change, the presence of the pipe operator will typically cause an
exception to be thrown due to the fact that the generated regexp is invalid.

The net result of this change is that ? and * operators will not be masked, and
pipe operators will need to be removed, although it's unexpected that these are
being used anywhere.

Closes #5920
2014-01-21 19:56:57 -05:00
George Cox
6d525f06c0 docs(tutorial): remove 'going forward' nonsense
Closes #5914

time/space dimension error
2014-01-21 16:45:27 -08:00
George Cox
d7e6f1b192 docs(tutorial): fix grammar
Closes #5909
2014-01-21 16:43:52 -08:00
Stéphane Reynaud
5b9ff6cf48 docs(guide/controller): fix duplicated "and" typo
Remove the second instance of the word "and" from the docs where it was duplicated.
2014-01-21 16:28:30 -08:00
Lucas Galfasó
f09b6aa5b5 fix($parse): do not use locals to resolve object properties
Do not use the locals when performing a field access in an angular expression.

Closes #5838
Closes #5862
2014-01-21 19:27:04 -05:00
Abraham
8b395ff325 docs(ngEventDirs): document priority of event directives
The general assumption is that if @priority is not defined, the priority is 0. BUT it's not
necessarily harmful to be explicit about this.

Closes #5852
2014-01-19 23:29:39 -05:00
Christoph Burgdorf
6c9131ef10 docs($http): remove outdated part about $http outside of $apply phase
This removes some outdated advice which no longer is true against the latest angular version.

The information about unit testing with ngMocks remains, because it's always good to have
information like that easily found. This little snippet is not worded perfectly, and is not
a very good example unit test, so additional work is needed here.

Relates to #5206
Closes #5485
2014-01-18 22:52:58 -05:00
Vlad GURDIGA
99c5027bf2 docs($provide): fix Markdown formatting for provider method
Indentation made Markdown parser think that it’s a block of code.

Closes #5446
2014-01-18 22:09:56 -05:00
letsmakesense
90e60d2d54 docs($q): note that function okToGreet is expected to be defined in example
the function okToGreet wasn't defined, so this example wouldn't work properly.

I've decided that instead of adding unrelated code to the example, it should just be noted that the
function is expected to be defined in the lexical scope.

Closes #5878
2014-01-18 17:36:58 -05:00
Bastian Buchholz
928d000db7 docs(ngInit): ng-init is an attribute/class directive, not an element directive
As discussed in comments on 42ec95ebae (commitcomment-5109829),
ngInit is not an element directive, so @clkao's example should reflect this.

Closes #5879
2014-01-18 17:10:46 -05:00
Chia-liang Kao
42ec95ebae docs(ngInit): note precedence when used with filters
Clears up expression priority issue

Closes #3869
Closes #5873
2014-01-18 15:35:33 -05:00
Joshua Flanagan
1028cfaa30 docs(services): use $log service in example consistently with $log API
The $log provider returns an object and not a function, so this example, which appears to be using
the $log provider, should call it as it would be called in a real-world application.

Closes #5875
2014-01-18 15:26:18 -05:00
Ben McCann
756c52d6c1 docs(directive): link to directive registration api function
Originally, this issue was regarding documenting `restrict: 'CM'` in the directive guide, but it
was pointed out that the restrict documentation is covered in the $compile documentation. Because of
this, a link was simply added to the $compile documentation.

However, the wording suggests that it's actually linking to the directive registration function, in
$compileProvider, so the docs will link there instead. There is a link only a paragraph below to the
$compile documentation, so this does not hurt.

Closes #5516
2014-01-17 22:36:05 -05:00
Jeff Jewiss
c3e1a41d6f docs(api): adds links to top level guides
The main api docs page is probably the main landing page for many devs
looking to learn angular, so linking to the main guide pages would
likely help.

Closes #5869
2014-01-17 19:19:27 -05:00
Abdessamad Idrissi
8dd4f14a04 docs(input): document ngValue directive
Extend the example with ng-value showing how to deal with default checked radio boxes.

Closes #5654
2014-01-17 18:15:25 -05:00
Cameron Spear
7ba30fd2e7 docs($sce): correct documentation for angular 1.2.0
Include mention of `ngSanitize` (and add it to the example), as well as removing (and clarifying if
needed) references to `ng-html-bind-unsafe`.

Closes #5551
2014-01-17 17:12:53 -05:00
Andreas Gruenbacher
5adea0ba64 docs(ngChange): clarify difference between ng-change DOM change event
The ng-change event triggers immediately, which makes a difference for text input fields and text
areas, where the JavaScript onchange event would only be called at the end of the change.

Closes #5640
2014-01-17 16:40:10 -05:00
Bruce Davidson
2262ca6697 docs(contributing): add instructions to install grunt-cli/bower globally on unix systems
Closes #5814
Closes #5811
2014-01-17 15:51:29 -05:00
刘朋飞
cd74f74468 docs(tutorial): add missing semicolon to code snippet
Lets encourage people to use semicolons in javascript :>

Closes #5834
2014-01-17 15:34:33 -05:00
Neil Rubens
fced1c0c16 docs(tutorial): fix typo
Correction misspelling: easist -> easiest

Closes #5850
2014-01-16 23:11:52 -05:00
Rob Wormald
1cdcddb5cc docs(animations): renamed animate-show-hide to sample-show-hide
This always throws me off - I think it helps to make it clear that the class name is arbitrary, and
what matters is the .ng-etc classes.

Closes #5848
2014-01-16 21:49:01 -05:00
Leniel Macaferi
0e4d7cacad docs(tutorial): reference node command before scripts\web-server.js
Amended to also clarify this note in the mac/linux tab.

Closes #5845
2014-01-16 19:13:53 -05:00
akerekes
6a9ccacd62 docs(concepts): fix typos in explanation
Code uses module names with '2' as suffix while the explanation used the module names without the
suffix. The diagram is correct but also does not suffix the module names.

Closes #5567
2014-01-15 19:31:06 -05:00
Foxandxss
e591ddcb30 docs(ngShowHide): make a note of values considered to be falsy
This issue has been a focus of problems for some users and we discussed it on the IRC that it should
be at least documented.

~Amended the style to use bootstrap notes, I think overall it looks better and catches the eyes more
easily. However there are no anchor links to these, if these are necessary they can be added later.

Closes #3436
Closes #5762
2014-01-15 17:59:01 -05:00
John Lannon
cd0af8a771 docs(README): fix typo
Closes #5813
2014-01-15 17:46:12 -05:00
Roy Ling
51a7f9dc4a docs(guide/directive): rephrase for consistency
- referring to `=attr` rather than `=prop` is consistent with note under example with =customerInfo
- change `prop` to `attr` (basically `prop` refers to property in JS object, `attr` is for HTML tag)
- change the function name in description to match the name in code example

Closes #5786
2014-01-15 17:41:17 -05:00
jenkins
61eb426ab4 chore(release): update cdn version 2014-01-15 13:39:34 -08:00
jenkins
8ea8da4f11 chore(release): start v1.2.10 (1.2.10) 2014-01-15 10:15:55 -08:00
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
Matias Niemelä
78ba429e6a chore(CHANGELOG): remove reverted commits from 1.2.4 2013-12-06 13:14:56 -05:00
Matias Niemelä
dbf8c3c745 revert: chore(Angular.js): Use call and === instead of apply and == in type check functions 2013-12-06 13:14:08 -05:00
Matias Niemelä
3602c9785b revert: chore($resource): Use shallow copy instead of angular.copy 2013-12-06 13:13:48 -05:00
Matias Niemelä
acaac21fd1 chore(release): cut 1.2.4 wormhole-blaster release 2013-12-06 12:46:25 -05:00
Matias Niemelä
c98ef94706 docs(CHANGELOG): add v1.2.4 changes 2013-12-06 12:46:01 -05:00
Tobias Bosch
b0972a2e75 fix($compile): update cloned elements if the template arrives after the cloning
If an element has a directive whose content is loaded using `templateUrl`,
and the element is cloned using a linking function before the template arrives,
the clone needs to be updated as well.

This also updates `ngIf` and `ngRepeat` to keep the connection to the clone
of a tranclude function, so that they know about the changes a directive with
`templateUrl` does to the element in the future.

Fixes to #4930.
2013-12-05 22:16:25 -08:00
Caitlin Potter
2dbb6f9a54 fix(isElement): return boolean value rather than truthy value.
angular.isElement currently returns a truthy object/function, or false. This
patch aims to correct this behaviour by casting the result of the isElement
expression to a boolean value via double-negation.

Closes #4519
Closes #4534
2013-12-05 17:14:05 -08:00
Karl Seamon
785a5fd7c1 chore(Angular.js): 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-05 16:43:11 -08:00
Karl Seamon
a55c1e79cf chore($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-05 16:13:04 -08:00
Karl Seamon
d070450cd2 chore(Scope): short-circuit after dirty-checking last dirty watcher
Stop dirty-checking during $digest after the last dirty watcher has been re-checked.

This prevents unneeded re-checking of the remaining watchers (They were already
checked in the previous iteration), bringing a substantial performance improvement
to the average case run time of $digest.

Closes #5272
Closes #5287
2013-12-05 15:37:37 -08:00
Andres Kalle
09648e4888 docs(tutorial/step-6): remove unused class="diagram"
Closes #5197
2013-12-05 22:17:07 +00:00
Pete Bacon Darwin
2adbcf189b docs(tutorial/step-3): remember to install karma plugins 2013-12-05 22:06:38 +00:00
Pete Bacon Darwin
39c5ffb2a6 docs(tutorial/step-2): remember to install karma plugins 2013-12-05 22:06:28 +00:00
Tobias Bosch
04a570d31c docs(TRIAGING): Initial doc about triaging issues in Angular 2013-12-05 09:36:14 -08:00
Matias Niemelä
958d3d56b1 fix($animate): ensure animations work with directives that share a transclusion
Closes #4716
Closes #4871
Closes #5021
Closes #5278
2013-12-05 10:54:19 -05:00
Caitlin Potter
0e50810c53 fix(ngInit): evaluate ngInit before ngInclude
The priority of ngInit is adjusted to occur before ngInclude, and after
ngController. This enables ngInit to initiallize values in a controller's
scope, and also to initiallize values before ngInclude executes.

Closes #5167
Closes #5208
2013-12-04 23:26:56 -08:00
Vojta Jina
21e48abbc1 chore(travis): move checks from before_scripts to scripts
If jshint (or any other ci-check) fails, Travis marks the build as "Errored" which I don't think is desider:
https://travis-ci.org/angular/angular.js/builds/14938896
2013-12-04 22:53:54 -08:00
Daniel Tabuenca
b6d5439343 fix(input): ensure ngModelWatch() triggers second digest pass when appropriate
Due to an earlier change, ngModelWatch() no longer returns a value to the
caller. This means the digest loop has no way to tell if the watch actually
modified anything and so can not schedule another pass.

This means any watches that watch form or model controller changes
(e.g. watches on form.$valid) that are scheduled prior to an ngModelWatch()
will not be able to see any changes made therin.

This commit fixes this behavior by returning the latest evaluated ng-model
value.

Closes #5258
Closes #5282
2013-12-04 22:49:11 -08:00
Matias Niemelä
93901bdde4 fix($animate): ensure ms durations are properly rounded
Closes #5113
Closes #5162
2013-12-04 19:26:40 -05:00
Jeff Cross
d802ed1b36 fix($rootScope): broadcast $destroy event on $rootScope
Fixes #5169
2013-12-04 15:29:19 -08:00
Sorin Gitlan
e8f4305e9d docs($interpolate): demonstrate a filter in the interpolated expression
Closes #5186
2013-12-04 22:36:42 +00:00
Iwona Lalik
b38a2287f2 docs(tutorial/step-3): add module to ng-app directive in code sample
Closes #5184
2013-12-04 22:36:42 +00:00
Julien Bouquillon
1e7675ad4c docs(input): remove deprecated isolated scope pitfall
The 1.2 release fixed the documented pitfall at 909cabd36d
by isolating only the isolated directive's scope.

Closes #5179
2013-12-04 22:36:41 +00:00
David Bennett
280b5ce3c0 chore(closure): add $routeProvider#redirectTo function parameters
Closes #5173
2013-12-04 22:36:41 +00:00
Elwin Arens
fbc5cf514b docs(tutorial/step-12): fix refernce to incorrect jquery version
Closes #5156
2013-12-04 22:36:40 +00:00
Mateusz Jedruch
f01087f802 fix(closure): closure compiler shouldn't rename .defaults.transformRequest 2013-12-04 14:01:34 -08:00
Yves Richard
4ac6424e87 docs(animate.js): fix copy/paste typo in leave docs
fix the copy/paste typo within $animate.leave method inside of the $animate docs.
2013-12-04 14:28:32 -05:00
Thomas Guillory
d3c486dd6d fix($rootScope): clear phase if an exception is raised by a watcher
Add calls to clearPhase() when an exception is raised by a watcher
while a digest cycle, in order to not be stuck on `$digest` scope phase
2013-12-04 10:11:29 -08:00
Daniel Tabuenca
2d0f6ccba8 fix($compile): ensure isolated local watches' lastValue is always in sync
When using two-way binding with isolate scope, under some circumstances
the lastValue variable captured in the parentValueWatch function can get
out of sync.

Specifically, if both the value in the origin scope as well as the value
in the isolate scope get independently updated to the same value within
one digest cycle, the lastValue is never updated. This potentially causes
the watch to make the wrong decision as to which side to update on subsequent
passes.

This fixes things by ensuring lastValue is always set to the last seen
value even if the watch's logic was short circuited because there was no
difference between the values in the original and isolate scopes.

Closes #5182
2013-12-04 09:45:20 -08:00
Vojta Jina
9a81b8668a chore(travis): give browsers more time to respond 2013-12-03 19:32:32 -08:00
Vojta Jina
9481d69d1c chore(travis): add IE 11 (SL) to the build 2013-12-03 19:32:32 -08:00
Vojta Jina
7615723547 chore: make it simpler to run tests on SL/BS during local development 2013-12-03 16:07:13 -08:00
Vojta Jina
338f949259 chore(travis): set SauceLabs build id 2013-12-03 15:49:19 -08:00
Vojta Jina
d0192b31a3 chore(travis): disable IE11
For some reason it's broken on SL.
2013-12-03 15:49:19 -08:00
Vojta Jina
6127528b50 chore(travis): switch back to SauceLabs
I think we are pretty close to be able to use both.

The xhr-polling seems to be pretty stable, but I'm having problems with multiple SSH tunnels (on BS), so let's try to switch back to SL.
2013-12-03 15:49:19 -08:00
Vojta Jina
0410572322 chore(travis): define a launcher for IE11 (SauceLabs) 2013-12-03 15:49:19 -08:00
Vojta Jina
fd2371cfc2 chore(travis): report both build number and id to BS 2013-12-03 15:49:19 -08:00
Vojta Jina
267fcc999c chore(travis): log used ports 2013-12-03 15:49:18 -08:00
Vojta Jina
84187b6d94 chore(travis): use different port numbers per build
We can't establish multiple SSH tunnels for the same port (for BrowserStack).
This makes it possible to run multiple parallel builds using BrowserStack.
2013-12-03 15:49:18 -08:00
Vojta Jina
5d6482bb3b chore(karma): correct the 404 ignoring 2013-12-03 15:49:18 -08:00
Naomi Black
023765c593 docs: fixed a typo and made a minor edit to docs section of CONTRIBUTING.md 2013-12-03 15:44:56 -08:00
Igor Minar
4a401bbcf3 style(Scope): remove extra ws 2013-12-03 15:44:13 -08:00
Igor Minar
7401c70718 style(Scope): rename child scope type from Child to ChildScope
This change makes it easier to debug angular, especiall when dealing with heap snapshots
and hunting for memory leaks.
2013-12-03 15:44:13 -08:00
Igor Minar
bb36bc7edf style(Angular.js): fix typo in comment 2013-12-03 15:44:13 -08:00
Michał Gołębiowski
bf1972dc1e fix(ngSanitize): prefer textContent to innerText to avoid layout trashing
innerText depends on styling as it doesn't display hidden elements.
Therefore, it's better to use textContent not to cause unnecessary
reflows. However, IE<9 don't support textContent so the innerText
fallback is necessary.
2013-12-03 14:45:30 -08:00
Karl Seamon
689dfb1679 chore($parse): micro-optimization for ensureSafeObject function
This version matches the "alternate 2.2" version here: http://jsperf.com/ensuresafeobject/2

alternate 2.3 is a bit faster and simpler, but would break backwards compatibility.

Closes #5246
2013-12-03 11:10:48 -08:00
Hubert SABLONNIÈRE
1169b54456 fix(jqLite): ignore incompatible nodes on find()
When a jqLite collection contains text nodes, find() does not work :-(

This fix ignores all nodes than can't do getElementsByTagName()

It seems a little bit faster than testing nodeType : http://jsperf.com/nodetype-vs-duck-typing

Closes #4120
2013-12-03 09:45:06 -08:00
Pete Bacon Darwin
81b81856ee fix($sanitize): don't rely on YARR regex engine executing immediately
In Safari 7 (and other browsers potentially using the latest YARR JIT library)
regular expressions are not always executed immediately that they are called.
The regex is only evaluated (lazily) when you first access properties on the `matches`
result object returned from the regex call.

In the case of `decodeEntities()`, we were updating this returned object, `parts[0] = ''`,
before accessing it, `if (parts[2])', and so our change was overwritten by the result
of executing the regex.

The solution here is not to modify the match result object at all. We only need to make use
of the three match results directly in code.

Developers should be aware, in the future, when using regex, to read from the result object
before making modifications to it.

There is no additional test committed here, because when run against Safari 7, this
bug caused numerous specs to fail, which are all fixed by this commit.

Closes #5193
Closes #5192
2013-12-03 13:35:09 +00:00
Vojta Jina
fd4b99936e chore(travis): increase BrowserStack timeout to 10min
Because IE is retarded.
2013-12-02 22:51:15 -08:00
Vojta Jina
09271a8ab9 chore(travis): ignore 404 warnings, debug log into file
This is a terrible hack/workaround, however I don't think there is any better way to achieve this
with log4js.
2013-12-02 22:51:15 -08:00
Naomi Black
5a8d9acacb docs: update CONTRIBUTING.MD with process for doc fixes 2013-12-02 16:23:59 -08:00
Vojta Jina
04d5a5072f chore(travis): fix the build id on browser stack
This just improves the way BrowserStack groups the sessions.
2013-12-02 14:43:44 -08:00
Vojta Jina
55c30e1be6 chore: use karma-browserstack-launcher from master 2013-12-02 14:20:14 -08:00
Vojta Jina
97fc84c151 chore(deps): use regular junit-reporter
We don't need the special branch anymore.
2013-12-02 14:20:06 -08:00
Vojta Jina
4ee0687f3f chore(travis): tolerate 2 disconnects to make the build more stable 2013-12-02 14:19:56 -08:00
Vojta Jina
ddff347b91 chore(travis): use only websockets and xhr-polling
I wanna see more info about BrowserStack...
2013-12-02 14:19:46 -08:00
James Brewer
05ef1bd853 chore(grunt): update to latest jshint task
Upgrade JSHint task from ~0.6.4 to ~0.7.2. Two useful changes: ability
to set jshintrc option to use jshint's native ability for finding .jshintrc
files relative to the linted files and update jshint to 2.3.0.

Closes #5143
2013-12-02 21:20:07 +00:00
Blaise Kal
d0f8bd30a6 docs($animate): require ngAnimate in example, syntax fixes
The example in the section "JavaScript-defined Animations" would not run without the ngAnimate dependency. Also added a missing comma and semicolons.
2013-12-02 14:55:34 -05:00
Peter Bacon Darwin
1a8d3c8b3a chore(docs): fix back-to-top anchor in angularjs.org doc pages
Closes https://github.com/angular/angularjs.org/issues/45
2013-11-28 12:16:07 +00:00
Levi Weiss
753687e5c2 docs(tutorial/step-10): fix typo
Closes #5171
2013-11-27 23:21:46 +00:00
Stéphane Reynaud
1a15c01b64 docs($compile): fix missing space 2013-11-27 23:20:09 +00:00
Ammar
7f33e1ca89 docs(tutorial/step-12): fix typo
Closes #5148
2013-11-27 23:19:02 +00:00
magoswiat
28d00945ba docs(tutorial/step-0): add target="_blank" to open app in new page
Closes #5145
2013-11-27 23:17:28 +00:00
Blaise Kal
6f40c88f47 docs(form): provide a list of Angular's built-in validation tokens
As requested by a top-rated Disqus comment: http://docs.angularjs.org/api/ng.directive:form.FormController#comment-655325797

Closes #5121
2013-11-27 23:06:19 +00:00
deepak-kapoor
68dd621082 docs(guide/concepts): fix incorrect module name in example
Closes #5116
2013-11-27 22:59:13 +00:00
wjtk
3abfb4ef51 docs($window): move use of $window to controller
Move use of `$window` from template to controller, because accessing `$window`
in expressions is now disallowed and doesn't work.

Closes #5110
2013-11-27 22:54:45 +00:00
Pete Bacon Darwin
1014e52349 docs($injector): use square bracket notation for $inject annotation
Closes #5104
2013-11-27 22:52:10 +00:00
Evan Winslow
cda061f723 docs(guide/di): use square bracket notation for $inject annotation
Closes #5104
2013-11-27 22:48:02 +00:00
Pavel Pomerantsev
1497c6c1fb docs(guide/providers): fix typo
Closes #5102
2013-11-27 22:41:53 +00:00
Marc Lipovsky
e41e445b51 docs(guide/compiler): add fourth step on appending the compiled template to the DOM
Closes #5087
2013-11-27 22:41:10 +00:00
rodyhaddad
7ab73190b7 docs(migration): add a note about "private" properties being reverted
Closes #5086
2013-11-27 22:35:09 +00:00
Peter Bacon Darwin
450b3a5460 chore(release): start 1.2.4 wormhole-baster iteration 2013-11-27 20:21:06 +00:00
Peter Bacon Darwin
38fb542838 chore(release): cut 1.2.3 unicorn-zapper release 2013-11-27 10:04:59 +00:00
Peter Bacon Darwin
7ab5098c14 docs(CHANGELOG): add v1.2.3 changes 2013-11-27 09:58:59 +00:00
Jeff Cross
bcca80548d feat($attrs): add $attrs.$attr to externs so that it isn't renamed
This fixes the issue that any usage of $attr is broken after js compilation.
2013-11-26 18:34:11 -08:00
Jeff Cross
736c8fbbae refactor($location): move file://+win path fix to $location
The urlResolve method was fixed to automatically remove the
volume label from path names to fix issues with the file
protocol on windows where $location.path() was returning
paths where the first segment would be the volume name,
such as "/C:/mypath". See #4942 and #4928

However, the solution was specific to the $location non-
HTML5 mode, and was implemented at a lower level of
abstraction than it should have been. This refactor moves
the fix to inside of the LocationHashBangUrl $$parse method.

Closes #5041
2013-11-26 18:31:27 -08:00
Igor Minar
947562220d chore(release): fix cdn version in package.json 2013-11-26 17:38:23 -08:00
Tobias Bosch
333523483f fix($sanitize): Use same whitelist mechanism as $compile does.
`$sanitize` now uses the same mechanism as `$compile` to validate uris.
By this, the validation in `$sanitize` is more general and can be
configured in the same way as the one in `$compile`.

Changes
- Creates the new private service `$$sanitizeUri`.
- Moves related specs from `compileSpec.js` into `sanitizeUriSpec.js`.
- Refactors the `linky` filter to be less dependent on `$sanitize`
  internal functions.

Fixes #3748.
2013-11-26 14:29:38 -08:00
corrupt
68ceb17272 chore($httpBackend): preserve original non-zero http status code for file:// apps
Previously if an app was running from file:// origin we would always return either
http 200 or 404 depending on whether the response was present.

This changes the behavior so that we do this only if the protocol of the request
(not the origin) is file:// and only if the status code is 0.

Closes #4436
Closes #4587
Closes #4514
2013-11-26 12:36:41 -08:00
David Mosher
5bd6596856 chore(mocks): wrap angular-mocks.js in closure
Closes #5080
2013-11-26 13:22:29 +00:00
Peter Bacon Darwin
b3f2a20832 chore(changelog): remove tmp file 2013-11-26 09:36:13 +00:00
adam77
e8d8c7a8d7 docs(compile): fix typo
Closes #5133
2013-11-26 06:56:38 +00:00
Deepak Kapoor
7a91d7fa7e docs(CONTRIBUTING): fix broken link to GitHub PR Helper
Closes #5134
2013-11-26 06:46:39 +00:00
smarigowda
c6bd58eb58 docs(guide/scope): access the current element's scope in the console.
Closes #4884
2013-11-26 06:45:48 +00:00
sunnylost
c2e45c769e refactor(angular.js): improve trim performance
According to Flagrant Badassery's blog
http://blog.stevenlevithan.com/archives/faster-trim-javascript
and this comparison http://jsperf.com/trim-function, this trim method is faster.

Closes #4406
2013-11-26 06:45:47 +00:00
Vojta Jina
b08427dde9 chore(travis): add some more info for BrowserStack sessions 2013-11-25 18:04:35 -08:00
Vojta Jina
ffd075b440 chore(travis): let's give BrowserStack a try
Switch the build to use BrowserStack instead of SauceLabs.

This also adds IE11 to our build.
2013-11-25 15:19:28 -08:00
Brian Ford
3fcd228441 chore: add script for updating bower repos 2013-11-25 13:09:50 -08:00
Pete Bacon Darwin
8383ecfcdf docs(CONTRIBUTING): add link to github-pr-helper 2013-11-25 20:18:36 +00:00
Matias Niemelä
eed2333298 fix(ngAnimate): ensure animations are disabled upon bootstrap for structrual animations
Closes #5130
2013-11-25 15:00:50 -05:00
Pete Bacon Darwin
a2809dacc4 docs(CONTRIBUTING): fix typo 2013-11-25 15:55:24 +00:00
Pete Bacon Darwin
b837a31afa docs(CONTRIBUTING): highlight what makes a good issue submission 2013-11-25 14:33:51 +00:00
Pete Bacon Darwin
66b0fcd3c0 docs(CONTRIBUTING): consolidated submitting PRs sections 2013-11-25 14:15:24 +00:00
Matias Niemelä
2efe82309a fix($animate): ensure blocked keyframe animations are unblocked before the DOM operation
Closes #5106
2013-11-23 22:05:04 -05:00
Tobias Bosch
a090400f09 fix(input): Support form auto complete on modern browser
Although modern browser support the "input" event, they still only fire
the "change" event when they auto complete form elements
other than the currently selected one.

Related to #1460
2013-11-22 17:02:21 -08:00
Brian Ford
84e0eea164 chore(docs): remove Disqus comments
We don't actively moderate these comments, and they range from
out of date, to inflammatory, to spam. Going forward, improvements
to the docs should be done via a PR, and questions should go on
StackOverflow where they can be curated and kept up to date by
AngularJS developers who help out there.
2013-11-22 16:27:05 -08:00
Igor Minar
bcf12e70e5 chore: update copyright year in file headers 2013-11-22 13:16:23 -08:00
Igor Minar
1ca98b2c09 chore(release): start 1.2.3 unicorn-zapper iteration 2013-11-22 12:43:52 -08:00
201 changed files with 9917 additions and 7737 deletions

1
.gitignore vendored
View file

@ -17,3 +17,4 @@ angular.xcodeproj
libpeerconnection.log libpeerconnection.log
npm-debug.log npm-debug.log
/tmp/ /tmp/
/scripts/bower/bower-*

3
.jscs.json Normal file
View file

@ -0,0 +1,3 @@
{
"disallowKeywords": ["with"]
}

22
.jscs.json.todo Normal file
View file

@ -0,0 +1,22 @@
// This is an incomplete TODO list of checks we want to start enforcing
//
// The goal is to enable these checks one by one by moving them to .jscs.json along with commits
// that correct the existing code base issues and make the new check pass.
{
"requireCurlyBraces": ["if", "else", "for", "while", "do", "try", "catch"],
"requireSpaceAfterKeywords": ["if", "else", "for", "while", "do", "switch", "return", "try", "catch"],
"disallowLeftStickedOperators": ["?", "+", "-", "/", "*", "=", "==", "===", "!=", "!==", ">", ">=", "<", "<="],
"disallowRightStickedOperators": ["?", "+", "/", "*", ":", "=", "==", "===", "!=", "!==", ">", ">=", "<", "<="],
"requireRightStickedOperators": ["!"],
"requireLeftStickedOperators": [","],
"disallowImplicitTypeConversion": ["string"],
"disallowMultipleLineBreaks": true,
"disallowKeywordsOnNewLine": ["else"],
"disallowTrailingWhitespace": true,
"requireLineFeedAtFileEnd": true,
"validateJSDoc": {
"checkParamNames": true,
"requireParamTypes": true
}
}

View file

@ -3,11 +3,14 @@ node_js:
- 0.10 - 0.10
env: env:
matrix:
- JOB=unit
- JOB=e2e
global: global:
- SAUCE_USERNAME=angular-ci - SAUCE_USERNAME=angular-ci
- SAUCE_ACCESS_KEY=9b988f434ff8-fbca-8aa4-4ae3-35442987 - SAUCE_ACCESS_KEY=9b988f434ff8-fbca-8aa4-4ae3-35442987
- SAUCE_CONNECT_READY_FILE=/tmp/sauce-connect-ready
- LOGS_DIR=/tmp/angular-build/logs - LOGS_DIR=/tmp/angular-build/logs
- BROWSER_PROVIDER_READY_FILE=/tmp/sauce-connect-ready
before_script: before_script:
- mkdir -p $LOGS_DIR - mkdir -p $LOGS_DIR
@ -16,11 +19,10 @@ before_script:
- grunt bower - grunt bower
- grunt bower - grunt bower
- grunt package-without-bower - grunt package-without-bower
- grunt ci-checks - ./scripts/travis/wait_for_browser_provider.sh
- ./lib/sauce/sauce_connect_block.sh
script: script:
- ./travis_build.sh - ./scripts/travis/build.sh
after_script: after_script:
- ./travis_print_logs.sh - ./scripts/travis/print_logs.sh

View file

@ -1,3 +1,405 @@
<a name="1.2.11"></a>
# 1.2.11 cryptocurrency-hyperdeflation (2014-02-03)
## Bug Fixes
- **$compile:** retain CSS classes added in cloneAttachFn on asynchronous directives
([5ed721b9](https://github.com/angular/angular.js/commit/5ed721b9b5e95ae08450e1ae9d5202e7f3f79295),
[#5439](https://github.com/angular/angular.js/issues/5439), [#5617](https://github.com/angular/angular.js/issues/5617))
- **$http:** update httpBackend to use ActiveXObject on IE8 if necessary
([ef210e5e](https://github.com/angular/angular.js/commit/ef210e5e119db4f5bfc9d2428b19f9b335c4f976),
[#5677](https://github.com/angular/angular.js/issues/5677), [#5679](https://github.com/angular/angular.js/issues/5679))
- **$q:** make $q.reject support `finally` and `catch`
([074b0675](https://github.com/angular/angular.js/commit/074b0675a1f97dce07f520f1ae6198ed3c604000),
[#6048](https://github.com/angular/angular.js/issues/6048), [#6076](https://github.com/angular/angular.js/issues/6076))
- **filterFilter:** don't interpret dots in predicate object fields as paths
([339a1658](https://github.com/angular/angular.js/commit/339a1658cd9bfa5e322a01c45aa0a1df67e3a842),
[#6005](https://github.com/angular/angular.js/issues/6005), [#6009](https://github.com/angular/angular.js/issues/6009))
- **mocks:** refactor currentSpec to work w/ Jasmine 2
([95f0bf9b](https://github.com/angular/angular.js/commit/95f0bf9b526fda8964527c6d4aef1ad50a47f1f3),
[#5662](https://github.com/angular/angular.js/issues/5662))
- **ngResource:** don't append number to '$' in url param value when encoding URI
([ce1f1f97](https://github.com/angular/angular.js/commit/ce1f1f97f0ebf77941b2bdaf5e8352d33786524d),
[#6003](https://github.com/angular/angular.js/issues/6003), [#6004](https://github.com/angular/angular.js/issues/6004))
<a name="1.2.10"></a>
# 1.2.10 augmented-serendipity (2014-01-24)
## Bug Fixes
- **$parse:** do not use locals to resolve object properties
([f09b6aa5](https://github.com/angular/angular.js/commit/f09b6aa5b58c090e3b8f8811fb7735e38d4b7623),
[#5838](https://github.com/angular/angular.js/issues/5838), [#5862](https://github.com/angular/angular.js/issues/5862))
- **a:** don't call preventDefault on click when a SVGAElement has an xlink:href attribute
([e0209169](https://github.com/angular/angular.js/commit/e0209169bf1463465ad07484421620748a4d3908),
[#5896](https://github.com/angular/angular.js/issues/5896), [#5897](https://github.com/angular/angular.js/issues/5897))
- **input:** use Chromium's email validation regexp
([79e519fe](https://github.com/angular/angular.js/commit/79e519fedaec54390a8bdacfb1926bfce57a1eb6),
[#5899](https://github.com/angular/angular.js/issues/5899), [#5924](https://github.com/angular/angular.js/issues/5924))
- **ngRoute:** pipe preceding route param no longer masks ? or * operator
([fd6bac7d](https://github.com/angular/angular.js/commit/fd6bac7de56f728a89782dc80c78f7d5c21bbc65),
[#5920](https://github.com/angular/angular.js/issues/5920))
## Features
- **$animate:** provide support for a close callback
([ca6b7d0f](https://github.com/angular/angular.js/commit/ca6b7d0fa2e355ebd764230260758cee9a4ebe1e),
[#5685](https://github.com/angular/angular.js/issues/5685), [#5053](https://github.com/angular/angular.js/issues/5053), [#4993](https://github.com/angular/angular.js/issues/4993))
<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))
## 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))
## Breaking Changes
- **$http:** due to [e1cfb195](https://github.com/angular/angular.js/commit/e1cfb1957feaf89408bccf48fae6f529e57a82fe),
it is now necessary to seperately specify default HTTP headers for PUT, POST and PATCH requests, as these no longer share a single object.
To migrate your code, follow the example below:
Before:
// Will apply to POST, PUT and PATCH methods
$httpProvider.defaults.headers.post = {
"X-MY-CSRF-HEADER": "..."
};
After:
// POST, PUT and PATCH default headers must be specified seperately,
// as they do not share data.
$httpProvider.defaults.headers.post =
$httpProvider.defaults.headers.put =
$httpProviders.defaults.headers.patch = {
"X-MY-CSRF-HEADER": "..."
};
<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)
## Bug Fixes
- **$animate:**
- ensure animations work with directives that share a transclusion
([958d3d56](https://github.com/angular/angular.js/commit/958d3d56b1899a2cfc7b18c0292e5a1d8c64d0a5),
[#4716](https://github.com/angular/angular.js/issues/4716), [#4871](https://github.com/angular/angular.js/issues/4871), [#5021](https://github.com/angular/angular.js/issues/5021), [#5278](https://github.com/angular/angular.js/issues/5278))
- ensure ms durations are properly rounded
([93901bdd](https://github.com/angular/angular.js/commit/93901bdde4bb9f0ba114ebb33b8885808e1823e1),
[#5113](https://github.com/angular/angular.js/issues/5113), [#5162](https://github.com/angular/angular.js/issues/5162))
- **$compile:**
- update cloned elements if the template arrives after the cloning
([b0972a2e](https://github.com/angular/angular.js/commit/b0972a2e75909e41dbac6e4413ada7df2d51df3a))
- ensure the isolated local watch `lastValue` is always in sync
([2d0f6ccb](https://github.com/angular/angular.js/commit/2d0f6ccba896fe34141d6d4f59eef6fba580c5c2),
[#5182](https://github.com/angular/angular.js/issues/5182))
- **$rootScope:**
- ensure that when the $destroy event is broadcast on $rootScope that it does something
([d802ed1b](https://github.com/angular/angular.js/commit/d802ed1b3680cfc1751777fac465b92ee29944dc),
[#5169](https://github.com/angular/angular.js/issues/5169))
- ensure the phase is cleared within a digest if an exception is raised by a watcher
([d3c486dd](https://github.com/angular/angular.js/commit/d3c486dd6dfa8d5dca32a3e28aa685fb7260c878))
- **$sanitize:** don't rely on YARR regex engine executing immediately in order to prevent object mutation
([81b81856](https://github.com/angular/angular.js/commit/81b81856ee43d2876927c4e1f774affa87e99707),
[#5193](https://github.com/angular/angular.js/issues/5193), [#5192](https://github.com/angular/angular.js/issues/5192))
- **closure:** closure compiler shouldn't rename .defaults.transformRequest
([f01087f8](https://github.com/angular/angular.js/commit/f01087f802839637843115cbcf99702e09d866f6))
- **input:** ensure ngModelWatch() triggers second digest pass when appropriate
([b6d54393](https://github.com/angular/angular.js/commit/b6d5439343b9801f7f2a009d0de09cba9aa21a1d),
[#5258](https://github.com/angular/angular.js/issues/5258), [#5282](https://github.com/angular/angular.js/issues/5282))
- **isElement:** return boolean value rather than `truthy` value.
([2dbb6f9a](https://github.com/angular/angular.js/commit/2dbb6f9a54eb5ff5847eed11c85ac4cf119eb41c),
[#4519](https://github.com/angular/angular.js/issues/4519), [#4534](https://github.com/angular/angular.js/issues/4534))
- **jqLite:** ignore incompatible nodes on find()
([1169b544](https://github.com/angular/angular.js/commit/1169b5445691e1495354d235a3badf05240e3904),
[#4120](https://github.com/angular/angular.js/issues/4120))
- **ngInit:** evaluate ngInit before ngInclude
([0e50810c](https://github.com/angular/angular.js/commit/0e50810c53428f4c1f5bfdba9599df54cb7a6c6e),
[#5167](https://github.com/angular/angular.js/issues/5167), [#5208](https://github.com/angular/angular.js/issues/5208))
- **ngSanitize:** prefer textContent to innerText to avoid layout trashing
([bf1972dc](https://github.com/angular/angular.js/commit/bf1972dc1e8ffbeaddfa53df1d49bc5a2177f09c))
## Performance Improvements
- **$parse:** micro-optimization for ensureSafeObject function
([689dfb16](https://github.com/angular/angular.js/commit/689dfb167924a61aef444ce7587fb987d8080990),
[#5246](https://github.com/angular/angular.js/issues/5246))
- **Scope:** short-circuit after dirty-checking last dirty watcher
([d070450c](https://github.com/angular/angular.js/commit/d070450cd2b3b3a3aa34b69d3fa1f4cc3be025dd),
[#5272](https://github.com/angular/angular.js/issues/5272), [#5287](https://github.com/angular/angular.js/issues/5287))
<a name="1.2.3"></a>
# 1.2.3 unicorn-zapper (2013-11-27)
## Bug Fixes
- **$animate:**
- ensure blocked keyframe animations are unblocked before the DOM operation
([2efe8230](https://github.com/angular/angular.js/commit/2efe82309ac8ff4f67df8b6e40a539ea31e15804),
[#5106](https://github.com/angular/angular.js/issues/5106))
- ensure animations are disabled during bootstrap to prevent unwanted structural animations
([eed23332](https://github.com/angular/angular.js/commit/eed2333298412fbad04eda97ded3487c845b9eb9),
[#5130](https://github.com/angular/angular.js/issues/5130))
- **$sanitize:** use the same whitelist mechanism as `$compile` does
([33352348](https://github.com/angular/angular.js/commit/333523483f3ce6dd3177b697a5e5a7177ca364c8),
[#3748](https://github.com/angular/angular.js/issues/3748))
- **input:** react to form auto completion, through the `change` event, on modern browsers
([a090400f](https://github.com/angular/angular.js/commit/a090400f09d7993d102f527609879cdc74abae60),
[#1460](https://github.com/angular/angular.js/issues/1460))
- **$attrs:** add `$attrs.$attr` to externs so that it isn't renamed on js minification
([bcca8054](https://github.com/angular/angular.js/commit/bcca80548dde85ffe3838c943ba8e5c2deb1c721))
## Features
No new features in this release
## Breaking Changes
There are no breaking changes in this release (promise!)
<a name="1.2.2"></a> <a name="1.2.2"></a>
# 1.2.2 consciousness-inertia (2013-11-22) # 1.2.2 consciousness-inertia (2013-11-22)
@ -4193,3 +4595,6 @@ with the `$route` service
[module]: http://docs-next.angularjs.org/api/angular.mock.module [module]: http://docs-next.angularjs.org/api/angular.mock.module
[guide2.di]: http://docs-next.angularjs.org/guide/dev_guide.di [guide2.di]: http://docs-next.angularjs.org/guide/dev_guide.di
[jqLite2]: http://docs.angularjs.org/#!/api/angular.element [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)

View file

@ -29,32 +29,124 @@ duplication of work, and help you to craft the change so that it is successfully
project. project.
* **Small Changes** can be crafted and submitted to [GitHub Repository][github] as a Pull Request. * **Small Changes** can be crafted and submitted to [GitHub Repository][github] as a Pull Request.
## Want a Doc Fix?
If you want to help improve the docs, it's a good idea to let others know what you're working on to
minimize duplication of effort. Before starting, check out the issue queue for [Milestone:Docs Only](https://github.com/angular/angular.js/issues?milestone=24&state=open).
Comment on an issue to let others know what you're working on, or create a new issue if your work
doesn't fit within the scope of any of the existing doc fix projects.
For large fixes, please build and test the documentation before submitting the PR to be sure you haven't
accidentally introduced any layout or formatting issues.You should also make sure that your commit message
is labeled "docs:" and follows the **Git Commit Guidelines** outlined below.
If you're just making a small change, don't worry about filing an issue first. Use the friendly blue "Improve this doc" button at the top right of the doc page to fork the repository in-place and make a quick change on the fly.
## Submission Guidelines ## Submission Guidelines
### Submitting an Issue ### Submitting an Issue
Before you submit your issue follow the following guidelines: Before you submit your issue search the archive, maybe your question was already answered.
* Search the archive first, it's likely that your question was already answered.
* A live example demonstrating the issue, will get an answer faster.
* Create one using [Plunker][plunker] or [JSFiddle][jsfiddle].
* If you get help, help others. Good karma rulez!
If your issue appears to be a bug, and hasn't been reported, open a new issue. If your issue appears to be a bug, and hasn't been reported, open a new issue.
Help us to maximize the effort we can spend fixing issues and adding new Help us to maximize the effort we can spend fixing issues and adding new
features, by not reporting duplicate issues. features, by not reporting duplicate issues. Providing the following information will increase the
chances of your issue being dealt with quickly:
* **Overview of the issue** - if an error is being thrown a non-minified stack trace helps
* **Motivation for or Use Case** - explain why this is a bug for you
* **Angular Version(s)** - is it a regression?
* **Browsers and Operating System** - is this a problem with all browsers or only IE8?
* **Reproduce the error** - provide a live example (using [Plunker][plunker] or
[JSFiddle][jsfiddle]) or a unambiguous set of steps.
* **Related issues** - has a similar issue been reported before?
* **Suggest a Fix** - if you can't fix the bug yourself, perhaps you can point to what might be
causing the problem (line of code or commit)
Here is a great example of a well defined issue: https://github.com/angular/angular.js/issues/5069
**If you get help, help others. Good karma rulez!**
### Submitting a Pull Request ### Submitting a Pull Request
Before you submit your pull request follow the following guidelines: Before you submit your pull request consider the following guidelines:
* Search GitHub for an open or closed Pull Request that relates to your submission. You don't want * Search [GitHub](https://github.com/angular/angular.js/pulls) for an open or closed Pull Request
to duplicate effort. that relates to your submission. You don't want to duplicate effort.
* Please sign our [Contributor License Agreement (CLA)](#signing-the-cla) before sending pull
requests. We cannot accept code without this.
* Make your changes in a new git branch * Make your changes in a new git branch
* Follow our Coding Rules
* Follow our Git Commit Guidelines ```shell
* Build your changes locally and on Travis (by pushing to GitHub) to ensure all the tests pass. git checkout -b my-fix-branch master
* Sign the Contributor License Agreement (CLA). We cannot accept code without this. ```
* Create your patch, including appropriate test cases.
* 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
`validate-commit-msg.js`):
```shell
git commit -a
```
* Build your changes locally to ensure all the tests pass
```shell
grunt test
```
* Push your branch to Github:
```shell
git push origin my-fix-branch
```
* In Github, send a pull request to `angular:master`.
* If we suggest changes then you can modify your branch, rebase and force a new push to your GitHub * If we suggest changes then you can modify your branch, rebase and force a new push to your GitHub
repository to update the Pull Request. repository to update the Pull Request:
```shell
git rebase master -i
git push -f
```
That's it! Thank you for your contribution!
When the patch is reviewed and merged, you can safely delete your branch and pull the changes
from the main (upstream) repository:
* Delete the remote branch on Github:
```shell
git push origin --delete my-fix-branch
```
* Check out the master branch:
```shell
git checkout master -f
```
* Delete the local branch:
```shell
git branch -D my-fix-branch
```
* Update your master with the latest upstream version:
```shell
git pull --ff upstream master
```
### GitHub Pull Request Helper
We track Pull Requests by attaching labels and assigning to milestones. For some reason GitHub
does not provide a good UI for managing labels on Pull Requests (unlike Issues). We have developed
a simple Chrome Extension that enables you to view (and manage if you have permission) the labels
on Pull Requests. You can get the extension from the Chrome WebStore -
[GitHub PR Helper][github-pr-helper]
## Coding Rules ## Coding Rules
To ensure consistency throughout the source code, keep these rules in mind as you are working: To ensure consistency throughout the source code, keep these rules in mind as you are working:
@ -106,6 +198,7 @@ Must be one of the following:
* **style**: Changes that do not affect the meaning of the code (white-space, formatting, missing * **style**: Changes that do not affect the meaning of the code (white-space, formatting, missing
semi-colons, etc) semi-colons, etc)
* **refactor**: A code change that neither fixes a bug or adds a feature * **refactor**: A code change that neither fixes a bug or adds a feature
* **perf**: A code change that improves performance
* **test**: Adding missing tests * **test**: Adding missing tests
* **chore**: Changes to the build process or auxiliary tools and libraries such as documentation * **chore**: Changes to the build process or auxiliary tools and libraries such as documentation
generation generation
@ -146,56 +239,6 @@ You can find out more detailed information about contributing in the
[AngularJS documentation][contributing]. [AngularJS documentation][contributing].
## Submitting Your Changes
To create and submit a change:
1. Please sign our [Contributor License Agreement (CLA)](#signing-the-cla) before sending pull
requests.
2. Create and checkout a new branch off the master branch for your changes:
```shell
git checkout -b my-fix-branch master
```
3. Create your patch, including appropriate test cases.
4. 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 `validate-commit-msg.js`):
```shell
git commit -a
```
5. Push your branch to Github:
```shell
git push origin my-fix-branch
```
6. In Github, send a pull request to `angular:master`.
That's it! Thank you for your contribution!
When the patch is reviewed and merged, you can safely delete your branch and pull the changes
from the main (upstream) repository:
```shell
# Delete the remote branch on Github:
git push origin :my-fix-branch
# Check out the master branch:
git checkout master
# Delete the local branch:
git branch -D my-fix-branch
# Update your master with the latest upstream version:
git pull --ff upstream master
```
[github]: https://github.com/angular/angular.js [github]: https://github.com/angular/angular.js
[Google Closure I18N library]: https://code.google.com/p/closure-library/source/browse/closure/goog/i18n/ [Google Closure I18N library]: https://code.google.com/p/closure-library/source/browse/closure/goog/i18n/
@ -214,3 +257,6 @@ git pull --ff upstream master
[individual-cla]: http://code.google.com/legal/individual-cla-v1.0.html [individual-cla]: http://code.google.com/legal/individual-cla-v1.0.html
[corporate-cla]: http://code.google.com/legal/corporate-cla-v1.0.html [corporate-cla]: http://code.google.com/legal/corporate-cla-v1.0.html
[commit-message-format]: https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y/edit# [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)

View file

@ -4,16 +4,8 @@ var path = require('path');
module.exports = function(grunt) { module.exports = function(grunt) {
//grunt plugins //grunt plugins
grunt.loadNpmTasks('grunt-contrib-clean'); require('load-grunt-tasks')(grunt);
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.loadNpmTasks('grunt-contrib-connect');
grunt.loadNpmTasks('grunt-contrib-compress');
grunt.loadNpmTasks('grunt-jasmine-node');
grunt.loadNpmTasks('grunt-ddescribe-iit');
grunt.loadNpmTasks('grunt-merge-conflict');
grunt.loadNpmTasks('grunt-parallel');
grunt.loadNpmTasks('grunt-shell');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadTasks('lib/grunt'); grunt.loadTasks('lib/grunt');
var NG_VERSION = util.getVersion(); var NG_VERSION = util.getVersion();
@ -86,9 +78,7 @@ module.exports = function(grunt) {
jqlite: 'karma-jqlite.conf.js', jqlite: 'karma-jqlite.conf.js',
jquery: 'karma-jquery.conf.js', jquery: 'karma-jquery.conf.js',
docs: 'karma-docs.conf.js', docs: 'karma-docs.conf.js',
modules: 'karma-modules.conf.js', modules: 'karma-modules.conf.js'
//NOTE run grunt test:e2e instead and it will start a webserver for you
end2end: 'karma-e2e.conf.js'
}, },
@ -100,51 +90,56 @@ module.exports = function(grunt) {
}, },
runprotractor: {
normal: 'protractor-conf.js'
},
clean: { clean: {
build: ['build'], build: ['build'],
tmp: ['tmp'] tmp: ['tmp']
}, },
jshint: { jshint: {
options: {
jshintrc: true,
},
ng: { ng: {
files: { src: files['angularSrc'] }, files: { src: files['angularSrc'] },
options: { jshintrc: 'src/.jshintrc' }
}, },
ngAnimate: { ngAnimate: {
files: { src: 'src/ngAnimate/**/*.js' }, files: { src: 'src/ngAnimate/**/*.js' },
options: { jshintrc: 'src/ngAnimate/.jshintrc' }
}, },
ngCookies: { ngCookies: {
files: { src: 'src/ngCookies/**/*.js' }, files: { src: 'src/ngCookies/**/*.js' },
options: { jshintrc: 'src/ngCookies/.jshintrc' }
}, },
ngLocale: { ngLocale: {
files: { src: 'src/ngLocale/**/*.js' }, files: { src: 'src/ngLocale/**/*.js' },
options: { jshintrc: 'src/ngLocale/.jshintrc' }
}, },
ngMock: { ngMock: {
files: { src: 'src/ngMock/**/*.js' }, files: { src: 'src/ngMock/**/*.js' },
options: { jshintrc: 'src/ngMock/.jshintrc' }
}, },
ngResource: { ngResource: {
files: { src: 'src/ngResource/**/*.js' }, files: { src: 'src/ngResource/**/*.js' },
options: { jshintrc: 'src/ngResource/.jshintrc' }
}, },
ngRoute: { ngRoute: {
files: { src: 'src/ngRoute/**/*.js' }, files: { src: 'src/ngRoute/**/*.js' },
options: { jshintrc: 'src/ngRoute/.jshintrc' }
}, },
ngSanitize: { ngSanitize: {
files: { src: 'src/ngSanitize/**/*.js' }, files: { src: 'src/ngSanitize/**/*.js' },
options: { jshintrc: 'src/ngSanitize/.jshintrc' }
}, },
ngScenario: { ngScenario: {
files: { src: 'src/ngScenario/**/*.js' }, files: { src: 'src/ngScenario/**/*.js' },
options: { jshintrc: 'src/ngScenario/.jshintrc' }
}, },
ngTouch: { ngTouch: {
files: { src: 'src/ngTouch/**/*.js' }, files: { src: 'src/ngTouch/**/*.js' },
options: { jshintrc: 'src/ngTouch/.jshintrc' } }
},
jscs: {
src: ['src/**/*.js', 'test/**/*.js'],
options: {
config: ".jscs.json"
} }
}, },
@ -178,7 +173,7 @@ module.exports = function(grunt) {
}, },
mocks: { mocks: {
dest: 'build/angular-mocks.js', dest: 'build/angular-mocks.js',
src: files['angularModules']['ngMock'], src: util.wrap(files['angularModules']['ngMock'], 'module'),
strict: false strict: false
}, },
sanitize: { sanitize: {
@ -275,18 +270,28 @@ module.exports = function(grunt) {
write: { write: {
versionTXT: {file: 'build/version.txt', val: NG_VERSION.full}, versionTXT: {file: 'build/version.txt', val: NG_VERSION.full},
versionJSON: {file: 'build/version.json', val: JSON.stringify(NG_VERSION)} versionJSON: {file: 'build/version.json', val: JSON.stringify(NG_VERSION)}
},
bump: {
options: {
files: ['package.json'],
commit: false,
createTag: false,
push: false
}
} }
}); });
//alias tasks //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:protractor']);
grunt.registerTask('test:jqlite', 'Run the unit tests with Karma' , ['tests:jqlite']); 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: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: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: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: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']); 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:e2e', 'Alias for test:protractor', ['test:protractor']);
grunt.registerTask('test:docgen', ['jasmine_node']); grunt.registerTask('test:docgen', ['jasmine_node']);
grunt.registerTask('test:promises-aplus',['build:promises-aplus-adapter','shell:promises-aplus-tests']); grunt.registerTask('test:promises-aplus',['build:promises-aplus-adapter','shell:promises-aplus-tests']);
@ -294,6 +299,6 @@ module.exports = function(grunt) {
grunt.registerTask('webserver', ['connect:devserver']); grunt.registerTask('webserver', ['connect:devserver']);
grunt.registerTask('package', ['bower','clean', 'buildall', 'minall', 'collect-errors', 'docs', 'copy', 'write', 'compress']); 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('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', 'jscs']);
grunt.registerTask('default', ['package']); grunt.registerTask('default', ['package']);
}; };

View file

@ -1,6 +1,6 @@
The MIT License The MIT License
Copyright (c) 2010-2012 Google, Inc. http://angularjs.org Copyright (c) 2010-2014 Google, Inc. http://angularjs.org
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

23
README.closure.md Normal file
View file

@ -0,0 +1,23 @@
Using AngularJS with the Closure Compiler
=========================================
The Closure Compiler project contains externs definitions for AngularJS
JavaScript in its `contrib/externs` directory.
The definitions contain externs for use with the Closure compiler (aka
JSCompiler). Passing these files to the --externs parameter of a compiler
pass allows using type annotations for AngularJS objects. For example,
Angular's $scope objects can be annotated as:
```js
/** @type {angular.Scope} */
var scope = $scope;
```
This allows JSCompiler to type check accesses to scope, give warnings about
missing methods or incorrect arguments, and also prevents renaming of property
accesses with advanced compilation.
The externs are incomplete and maintained on an as-needed basis, but strive to
be correct. Externs for individual modules should be added in separate files.
See https://developers.google.com/closure/compiler/

View file

@ -7,7 +7,7 @@ syntax to express your applications components clearly and succinctly. It au
synchronizes data from your UI (view) with your JavaScript objects (model) through 2-way data synchronizes data from your UI (view) with your JavaScript objects (model) through 2-way data
binding. To help you structure your application better and make it easy to test, AngularJS teaches binding. To help you structure your application better and make it easy to test, AngularJS teaches
the browser how to do dependency injection and inversion of control. Oh yeah and it also helps with the browser how to do dependency injection and inversion of control. Oh yeah and it also helps with
server-side communication, taming async callbacks with promises and deferreds; and make client-side server-side communication, taming async callbacks with promises and deferreds; and makes client-side
navigation and deeplinking with hashbang urls or HTML5 pushState a piece of cake. The best of all: navigation and deeplinking with hashbang urls or HTML5 pushState a piece of cake. The best of all:
it makes development fun! it makes development fun!
@ -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 To learn more about the grunt tasks, run `grunt --help` and also read our
[contribution guidelines](http://docs.angularjs.org/misc/contribute). [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)

63
TRIAGING.md Normal file
View file

@ -0,0 +1,63 @@
# Triage new issues/PRs on github
This document shows the steps the Angular team is using to triage issues.
The labels are used later on for planning releases.
## Tips ##
* install [github pr helper extension](https://github.com/petebacondarwin/github-pr-helper) and become 356% more productive
* Label "resolution:*"
* 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)
1. Assign yourself: Pick an issue that is not assigned to anyone and assign it to you
1. Assign milestone:
* "Docs only" milestone - for documentation PR -> **Done**.
* Current/next milestone - regressions
* 1.2.x - everything else
1. Label "GH: *" (to be automated via Mary Poppins)
* PR - issue is a PR
* issue - otherwise
1. Bugs:
* Label "Type: Bug"
* Label "Type: Regression" - if the bug is a regression
* Duplicate? - Check if there are comments pointing out that this is a dupe, if they do exist verify that this is indeed a dupe and close it and go to the last step
* Reproducible? - Steps to reproduce the bug are clear, if not ask for clarification (ideally plunker or fiddle)
* Reproducible on master? - http://code.angularjs.org/snapshot/
1. Non bugs:
* 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.
1. Label "component: *"
* In rare cases, it's ok to have multiple components.
1. Label "impact: *"
* small - obscure issue affecting one or handful of developers
* medium - impacts some usage patterns
* large - impacts most or all of angular apps
1. Label "complexity: *"
* small - trivial change
* medium - non-trivial but straightforward change
* large - changes to many components in angular or any changes to $compile, ngRepeat or other "fun" components
1. Label "PRs plz!" for "GH: issue"
* if complexity is small or medium and the problem as well as solution are well captured in the issue
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)

1
angularFiles.js vendored
View file

@ -27,6 +27,7 @@ angularFiles = {
'src/ng/parse.js', 'src/ng/parse.js',
'src/ng/q.js', 'src/ng/q.js',
'src/ng/rootScope.js', 'src/ng/rootScope.js',
'src/ng/sanitizeUri.js',
'src/ng/sce.js', 'src/ng/sce.js',
'src/ng/sniffer.js', 'src/ng/sniffer.js',
'src/ng/timeout.js', 'src/ng/timeout.js',

View file

@ -142,6 +142,7 @@ var writeChangelog = function(stream, commits, version) {
var sections = { var sections = {
fix: {}, fix: {},
feat: {}, feat: {},
perf: {},
breaks: {} breaks: {}
}; };
@ -169,6 +170,7 @@ var writeChangelog = function(stream, commits, version) {
stream.write(util.format(HEADER_TPL, version, version, currentDate())); stream.write(util.format(HEADER_TPL, version, version, currentDate()));
printSection(stream, 'Bug Fixes', sections.fix); printSection(stream, 'Bug Fixes', sections.fix);
printSection(stream, 'Features', sections.feat); printSection(stream, 'Features', sections.feat);
printSection(stream, 'Performance Improvements', sections.perf);
printSection(stream, 'Breaking Changes', sections.breaks, false); printSection(stream, 'Breaking Changes', sections.breaks, false);
} }
@ -186,7 +188,7 @@ var getPreviousTag = function() {
var generate = function(version, file) { var generate = function(version, file) {
getPreviousTag().then(function(tag) { getPreviousTag().then(function(tag) {
console.log('Reading git log since', 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('Parsed', commits.length, 'commits');
console.log('Generating changelog to', file || 'stdout', '(', version, ')'); console.log('Generating changelog to', file || 'stdout', '(', version, ')');
writeChangelog(file ? fs.createWriteStream(file) : process.stdout, commits, version); writeChangelog(file ? fs.createWriteStream(file) : process.stdout, commits, version);

View file

@ -1,80 +0,0 @@
<a name="v1.0.0rc3"></a>
# v1.0.0rc3 (2012-03-27)
## Bug Fixes
- **$compile:**
- create new (isolate) scopes for directives on root elements ([5390fb37](https://github.com/angular/angular.js/commit/5390fb37d2c01937922613fc57df4986af521787), closes [#817](https://github.com/angular/angular.js/issues/817))
- don't touch static element attributes ([9cb2195e](https://github.com/angular/angular.js/commit/9cb2195e61a78e99020ec19d687a221ca88b5900))
- Merge interpolated css class when replacing an element ([f49eaf8b](https://github.com/angular/angular.js/commit/f49eaf8bf2df5f4e0e82d6c89e849a4f82c8d414))
- **$http:**
- don't send Content-Type header when no data ([1a5bebd9](https://github.com/angular/angular.js/commit/1a5bebd927ecd22f9c34617642fdf58fe3f62efb), closes [#749](https://github.com/angular/angular.js/issues/749))
- **$log:**
- avoid console.log.apply calls in IE ([15213ec2](https://github.com/angular/angular.js/commit/15213ec212769837cb2b7e781ffc5bfd598d27ca), closes [#805](https://github.com/angular/angular.js/issues/805))
- **$resource:**
- support escaping of ':' in resource url ([6d6f8753](https://github.com/angular/angular.js/commit/6d6f875345e01f2c6c63ef95164f6f39e923da15))
- **compiler:**
- allow transclusion of root elements ([9918b748](https://github.com/angular/angular.js/commit/9918b748be01266eb10db39d51b4d3098d54ab66))
- **e2e runner:**
- fix typo that caused errors on IE8 ([ee5a5352](https://github.com/angular/angular.js/commit/ee5a5352fd4b94cedee6ef20d4bf2d43ce77e00b), closes [#806](https://github.com/angular/angular.js/issues/806))
- **forEach:**
- should ignore prototypically inherited properties ([8d7e6948](https://github.com/angular/angular.js/commit/8d7e6948496ff26ef1da8854ba02fcb8eebfed61), closes [#813](https://github.com/angular/angular.js/issues/813))
- **forms:**
- Remove double registering of form ([1faafa31](https://github.com/angular/angular.js/commit/1faafa31582c4e9413f48dc7d12f5b681f9fe9fd))
- Set ng-valid/ng-invalid correctly ([08bfea18](https://github.com/angular/angular.js/commit/08bfea183a850b29da270eac47f80b598cbe600f))
- **init:**
- use jQuery#ready for init if available ([cb2ad9ab](https://github.com/angular/angular.js/commit/cb2ad9abf24e6f855cc749efe3155bd7987ece9d), closes [#818](https://github.com/angular/angular.js/issues/818))
- **json:**
- added support for iso8061 timezone ([5ac14f63](https://github.com/angular/angular.js/commit/5ac14f633a69f49973b5512780c6ec7752405967))
- **matchers.toHaveClass:**
- Correct reference to angular.mock.dump ([f701ce08](https://github.com/angular/angular.js/commit/f701ce08f9d63be05fc3b92f57ad473e1e749b2d))
- **ng-switch:**
- properly destroy child scopes ([2315d9b3](https://github.com/angular/angular.js/commit/2315d9b3610994b36c44e4a97fb1427d59471ce8))
- **ngDocSpec:**
- fix broken tests ([53b6f522](https://github.com/angular/angular.js/commit/53b6f522a56eea314cbd084816e08f24b2c7879f))
- **ngForm:**
- alias name||ngForm ([823adb23](https://github.com/angular/angular.js/commit/823adb231995e917bc060bfa49453e2a96bac2b6))
- **ngRepeat:**
- correct variable reference in error message ([935c1018](https://github.com/angular/angular.js/commit/935c1018da05dbf3124b2dd33619c4a3c82d7a2a))
- **ngView:**
- controller not published ([21e74c2d](https://github.com/angular/angular.js/commit/21e74c2d2e8e985b23711785287feb59965cbd90))
- **q:**
- resolve all of nothing to nothing ([ac75079e](https://github.com/angular/angular.js/commit/ac75079e2113949d5d64adbcf23d56f3cf295d41))
- **select:**
- multiselect failes to update view on selection insert ([6ecac8e7](https://github.com/angular/angular.js/commit/6ecac8e71a84792a434d21db2c245b3648c55f18))
## Features
- **$compile:**
- do not interpolate boolean attributes, rather evaluate them ([a08cbc02](https://github.com/angular/angular.js/commit/a08cbc02e78e789a66e9af771c410e8ad1646e25))
- **$controller:**
- support controller registration via $controllerProvider ([d54dfecb](https://github.com/angular/angular.js/commit/d54dfecb00fba41455536c5ddd55310592fdaf84))
- **$route:**
- when matching consider trailing slash as optional ([a4fe51da](https://github.com/angular/angular.js/commit/a4fe51da3ba0dc297ecd389e230d6664f250c9a6), closes [#784](https://github.com/angular/angular.js/issues/784))
- **assertArgFn:**
- should support array annotated fns ([4b8d9260](https://github.com/angular/angular.js/commit/4b8d926062eb4d4483555bdbdec4656f585ab40b))
- **http:**
- added params parameter ([73c85930](https://github.com/angular/angular.js/commit/73c8593077155a9f2e8ef42efd4c497eba0bef4f))
- **injector:**
- infer _foo_ as foo ([f13dd339](https://github.com/angular/angular.js/commit/f13dd3393dfb7a33565c9360342c193bc0bddcb6))
- **input.radio:**
- Allow value attribute to be interpolated ([ade6c452](https://github.com/angular/angular.js/commit/ade6c452753145c84884d17027a7865bf4b34b0c))
- **jqLite:**
- make injector() and scope() work with the document object ([5fdab52d](https://github.com/angular/angular.js/commit/5fdab52dd7c269f99839f4fa6b5854d9548269fa))
- add .controller() method ([6c5a05ad](https://github.com/angular/angular.js/commit/6c5a05ad49a1e083570c3dfe331403398f899dbe))
- **ngValue:**
- allow radio inputs to have non string values ([09e175f0](https://github.com/angular/angular.js/commit/09e175f02cca0f4a295fd0c9b980cd8f432e722b), closes [#816](https://github.com/angular/angular.js/issues/816))
- **scope:**
- broadcast $destroy event on scope destruction ([9b1aff90](https://github.com/angular/angular.js/commit/9b1aff905b638aa274a5fc8f88662df446d374bd))
- **scope.$eval:**
- Allow passing locals to the expression ([192ff61f](https://github.com/angular/angular.js/commit/192ff61f5d61899e667c6dbce4d3e6e399429d8b))
## Breaking Changes
- boolean attrs are evaluated rather than interpolated ([a08cbc02](https://github.com/angular/angular.js/commit/a08cbc02e78e789a66e9af771c410e8ad1646e25))
- ng-bind-attr directive removed ([55027132](https://github.com/angular/angular.js/commit/55027132f3d57e5dcf94683e6e6bd7b0aae0087d))
- any app that depends on this service and its fallback to Modernizr, please ([aaedefb9](https://github.com/angular/angular.js/commit/aaedefb92e6bec6626e173e5155072c91471596a))

View file

@ -1,17 +0,0 @@
This file contains externs for use with the Closure compiler (aka JSCompiler).
Passing these files to the --externs parameter of a compiler pass allows using
type annotations for AngularJS objects. For example, Angular's $scope objects
can be annotated as:
```js
/** @type {angular.Scope} */
var scope = $scope;
```
This allows JSCompiler to type check accesses to scope, give warnings about
missing methods or incorrect arguments, and also prevents renaming of property
accesses with advanced compilation.
The externs are incomplete and maintained on an as-needed basis, but strive to
be correct. Externs for individual modules should be added in separate files.
See https://developers.google.com/closure/compiler/

1912
closure/angular.js vendored

File diff suppressed because it is too large Load diff

View file

@ -9,14 +9,3 @@
ng\:form { ng\:form {
display: block; 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; }

View file

@ -5,7 +5,7 @@ describe('Docs Annotations', function() {
var body; var body;
beforeEach(function() { beforeEach(function() {
body = angular.element(document.body); body = angular.element(document.body);
body.html(''); body.empty();
}); });
var normalizeHtml = function(html) { var normalizeHtml = function(html) {

View file

@ -13,8 +13,7 @@ describe("docsSearch", function() {
results[0] = { section: 'tutorial', shortName: 'item one', keywords: 'item, one, 1' }; results[0] = { section: 'tutorial', shortName: 'item one', keywords: 'item, one, 1' };
results[1] = { section: 'tutorial', shortName: 'item man', keywords: 'item, man' }; results[1] = { section: 'tutorial', shortName: 'item man', keywords: 'item, man' };
results[2] = { section: 'api', shortName: 'item other', keywords: 'item, other' }; results[2] = { section: 'api', shortName: 'item other', keywords: 'item, other' };
results[3] = { section: 'cookbook', shortName: 'item cookbook', keywords: 'item, other' }; results[3] = { section: 'api', shortName: 'ngRepeat', keywords: 'item, other' };
results[4] = { section: 'api', shortName: 'ngRepeat', keywords: 'item, other' };
$provide.value('NG_PAGES', results); $provide.value('NG_PAGES', results);
$provide.factory('lunrSearch', function() { $provide.factory('lunrSearch', function() {
@ -41,19 +40,14 @@ describe("docsSearch", function() {
expect(items['api'].length).toBe(2); expect(items['api'].length).toBe(2);
})); }));
it("should place cookbook items in the tutorial", inject(function(docsSearch) {
var items = docsSearch('item');
expect(items['tutorial'].length).toBe(3);
}));
it("should return all results without a search", inject(function(docsSearch) { it("should return all results without a search", inject(function(docsSearch) {
var items = docsSearch(); var items = docsSearch();
expect(items['tutorial'].length).toBe(3); expect(items['tutorial'].length).toBe(2);
expect(items['api'].length).toBe(2); expect(items['api'].length).toBe(2);
})); }));
it("should store values with and without a ng prefix", inject(function(docsSearch) { it("should store values with and without a ng prefix", inject(function(docsSearch) {
expect(interceptedLunrResults[4].title).toBe('ngRepeat repeat'); expect(interceptedLunrResults[3].title).toBe('ngRepeat repeat');
})); }));
}); });

View file

@ -28,7 +28,7 @@ function escape(text) {
function setHtmlIe8SafeWay(element, html) { function setHtmlIe8SafeWay(element, html) {
var newElement = angular.element('<pre>' + html + '</pre>'); var newElement = angular.element('<pre>' + html + '</pre>');
element.html(''); element.empty();
element.append(newElement.contents()); element.append(newElement.contents());
return element; return element;
} }
@ -215,17 +215,7 @@ directive.ngEmbedApp = ['$templateCache', '$browser', '$rootScope', '$location',
}]; }];
this.html5Mode = angular.noop; 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) { $provide.decorator('$rootScope', ['$delegate', function($delegate) {
embedRootScope = $delegate; embedRootScope = $delegate;

View file

@ -5,8 +5,8 @@
# AngularJS API Docs # AngularJS API Docs
Welcome to the AngularJS API docs page. These pages contain the AngularJS reference materials for version <strong ng-bind="version"></strong>. Welcome to the AngularJS API docs page. These pages contain the AngularJS reference materials for version <strong ng-bind="version"></strong>.
The documentation is organized into **modules** which contain various components of an AngularJS application. The documentation is organized into **{@link guide/module modules}** which contain various components of an AngularJS application.
These components are directives, services, filters, providers, types, global APIs and testing mocks. These components are {@link guide/directive directives}, {@link guide/dev_guide.services services}, {@link guide/filter filters}, {@link guide/providers providers}, {@link guide/templates types}, global APIs and testing mocks.
<div class="alert alert-info"> <div class="alert alert-info">
**Angular Namespaces `$` and `$$`** **Angular Namespaces `$` and `$$`**
@ -63,7 +63,7 @@ This module is provided by default and contains the core components of AngularJS
</td> </td>
<td> <td>
<p> <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>
<p> <p>
Some examples include: Some examples include:

View file

@ -3,6 +3,9 @@
@description @description
# ng (core module) # 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> <div doc-module-components="ng"></div>

View file

@ -1,122 +0,0 @@
@ngdoc overview
@name Cookbook: Advanced Form
@description
Here we extend the basic form example to include common features such as reverting, dirty state
detection, and preventing invalid form submission.
<doc:example>
<doc:source>
<script>
function UserForm($scope) {
var master = {
name: 'John Smith',
address:{
line1: '123 Main St.',
city:'Anytown',
state:'AA',
zip:'12345'
},
contacts:[
{type:'phone', value:'1(234) 555-1212'}
]
};
$scope.state = /^\w\w$/;
$scope.zip = /^\d\d\d\d\d$/;
$scope.cancel = function() {
$scope.form = angular.copy(master);
};
$scope.save = function() {
master = $scope.form;
$scope.cancel();
};
$scope.addContact = function() {
$scope.form.contacts.push({type:'', value:''});
};
$scope.removeContact = function(index) {
$scope.form.contacts.splice(index, 1);
};
$scope.isCancelDisabled = function() {
return angular.equals(master, $scope.form);
};
$scope.isSaveDisabled = function() {
return $scope.myForm.$invalid || angular.equals(master, $scope.form);
};
$scope.cancel();
}
</script>
<div ng-controller="UserForm">
<form name="myForm">
<label>Name:</label><br/>
<input type="text" ng-model="form.name" required/> <br/><br/>
<label>Address:</label> <br/>
<input type="text" ng-model="form.address.line1" size="33" required/> <br/>
<input type="text" ng-model="form.address.city" size="12" required/>,
<input type="text" ng-model="form.address.state" size="2"
ng-pattern="state" required/>
<input type="text" ng-model="form.address.zip" size="5"
ng-pattern="zip" required/><br/><br/>
<label>Contacts:</label>
[ <a href="" ng-click="addContact()">add</a> ]
<div ng-repeat="contact in form.contacts">
<select ng-model="contact.type">
<option>email</option>
<option>phone</option>
<option>pager</option>
<option>IM</option>
</select>
<input type="text" ng-model="contact.value" required/>
[ <a href="" ng-click="removeContact($index)">X</a> ]
</div>
<button ng-click="cancel()" ng-disabled="isCancelDisabled()">Cancel</button>
<button ng-click="save()" ng-disabled="isSaveDisabled()">Save</button>
</form>
<hr/>
Debug View:
<pre>form={{form}}</pre>
</div>
</doc:source>
<doc:scenario>
it('should enable save button', function() {
expect(element(':button:contains(Save)').attr('disabled')).toBeTruthy();
input('form.name').enter('');
expect(element(':button:contains(Save)').attr('disabled')).toBeTruthy();
input('form.name').enter('change');
expect(element(':button:contains(Save)').attr('disabled')).toBeFalsy();
element(':button:contains(Save)').click();
expect(element(':button:contains(Save)').attr('disabled')).toBeTruthy();
});
it('should enable cancel button', function() {
expect(element(':button:contains(Cancel)').attr('disabled')).toBeTruthy();
input('form.name').enter('change');
expect(element(':button:contains(Cancel)').attr('disabled')).toBeFalsy();
element(':button:contains(Cancel)').click();
expect(element(':button:contains(Cancel)').attr('disabled')).toBeTruthy();
expect(element(':input[ng\\:model="form.name"]').val()).toEqual('John Smith');
});
</doc:scenario>
</doc:example>
#Things to notice
* Cancel & save buttons are only enabled if the form is dirty — there is something to cancel or
save.
* Save button is only enabled if there are no validation errors on the form.
* Cancel reverts the form changes back to original state.
* Save updates the internal model of the form.
* Debug view shows the two models. One presented to the user form and the other being the pristine
copy master.

View file

@ -1,63 +0,0 @@
@ngdoc overview
@name Cookbook: Resources - Buzz
@description
External resources are URLs that provide JSON data, which are then rendered with the help of
templates. Angular has a resource factory that can be used to give names to the URLs and then
attach behavior to them. For example you can use the
{@link http://code.google.com/apis/buzz/v1/getting_started.html#background-operations| Google Buzz
API}
to retrieve Buzz activity and comments.
<doc:example>
<doc:source>
<script>
BuzzController.$inject = ['$scope', '$resource'];
function BuzzController($scope, $resource) {
$scope.userId = 'googlebuzz';
$scope.Activity = $resource(
'https://www.googleapis.com/buzz/v1/activities/:userId/:visibility/:activityId/:comments',
{alt: 'json', callback: 'JSON_CALLBACK'},
{ get: {method: 'JSONP', params: {visibility: '@self'}},
replies: {method: 'JSONP', params: {visibility: '@self', comments: '@comments'}}
});
$scope.fetch = function() {
$scope.activities = $scope.Activity.get({userId:this.userId});
}
$scope.expandReplies = function(activity) {
activity.replies = $scope.Activity.replies({userId: this.userId, activityId: activity.id});
}
};
</script>
<div ng-controller="BuzzController">
<input ng-model="userId"/>
<button ng-click="fetch()">fetch</button>
<hr/>
<div class="buzz" ng-repeat="item in activities.data.items">
<h1 style="font-size: 15px;">
<img ng-src="{{item.actor.thumbnailUrl}}" style="max-height:30px;max-width:30px;"/>
<a ng-href="{{item.actor.profileUrl}}">{{item.actor.name}}</a>
<a href ng-click="expandReplies(item)" style="float: right;">
Expand replies: {{item.links.replies[0].count}}
</a>
</h1>
{{item.object.content | html}}
<div class="reply" ng-repeat="reply in item.replies.data.items" style="margin-left: 20px;">
<img ng-src="{{reply.actor.thumbnailUrl}}" style="max-height:30px;max-width:30px;"/>
<a ng-href="{{reply.actor.profileUrl}}">{{reply.actor.name}}</a>:
{{reply.content | html}}
</div>
</div>
</div>
</doc:source>
<doc:scenario>
xit('fetch buzz and expand', function() {
element(':button:contains(fetch)').click();
expect(repeater('div.buzz').count()).toBeGreaterThan(0);
element('.buzz a:contains(Expand replies):first').click();
expect(repeater('div.reply').count()).toBeGreaterThan(0);
});
</doc:scenario>
</doc:example>

View file

@ -1,151 +0,0 @@
@ngdoc overview
@name Cookbook: Deep Linking
@description
Deep linking allows you to encode the state of the application in the URL so that it can be
bookmarked and the application can be restored from the URL to the same state.
While Angular does not force you to deal with bookmarks in any particular way, it has services
which make the common case described here very easy to implement.
# Assumptions
Your application consists of a single HTML page which bootstraps the application. We will refer
to this page as the chrome.
Your application is divided into several screens (or views) which the user can visit. For example,
the home screen, settings screen, details screen, etc. For each of these screens, we would like to
assign a URL so that it can be bookmarked and later restored. Each of these screens will be
associated with a controller which define the screen's behavior. The most common case is that the
screen will be constructed from an HTML snippet, which we will refer to as the partial. Screens can
have multiple partials, but a single partial is the most common construct. This example makes the
partial boundary visible using a blue line.
You can make a routing table which shows which URL maps to which partial view template and which
controller.
# Example
In this example we have a simple app which consist of two screens:
* Welcome: url `welcome` Show the user contact information.
* Settings: url `settings` Show an edit screen for user contact information.
<example module="deepLinking" deps="angular-route.js, angular-sanitize.js">
<file name="script.js">
angular.module('deepLinking', ['ngRoute', 'ngSanitize'])
.config(function($routeProvider) {
$routeProvider.
when("/welcome", {templateUrl:'welcome.html', controller:WelcomeCntl}).
when("/settings", {templateUrl:'settings.html', controller:SettingsCntl});
});
AppCntl.$inject = ['$scope', '$route']
function AppCntl($scope, $route) {
$scope.$route = $route;
// initialize the model to something useful
$scope.person = {
name:'anonymous',
contacts:[{type:'email', url:'anonymous@example.com'}]
};
}
function WelcomeCntl($scope) {
$scope.greet = function() {
alert("Hello " + $scope.person.name);
};
}
function SettingsCntl($scope, $location) {
$scope.cancel = function() {
$scope.form = angular.copy($scope.person);
};
$scope.save = function() {
angular.copy($scope.form, $scope.person);
$location.path('/welcome');
};
$scope.cancel();
}
</file>
<file name="style.css">
[ng-view] {
border: 1px solid blue;
margin: 0;
padding:1em;
}
.partial-info {
background-color: blue;
color: white;
padding: 3px;
}
</file>
<file name="index.html">
<div ng-controller="AppCntl">
<h1>Your App Chrome</h1>
[ <a href="welcome">Welcome</a> | <a href="settings">Settings</a> ]
<hr/>
<span class="partial-info">
Partial: {{$route.current.template}}
</span>
<div ng-view></div>
<small>Your app footer </small>
</div>
</file>
<file name="settings.html">
<label>Name:</label>
<input type="text" ng:model="form.name" required>
<div ng:repeat="contact in form.contacts">
<select ng:model="contact.type">
<option>url</option>
<option>email</option>
<option>phone</option>
</select>
<input type="text" ng:model="contact.url">
[ <a href="" ng:click="form.contacts.$remove(contact)">X</a> ]
</div>
<div>
[ <a href="" ng:click="form.contacts.$add()">add</a> ]
</div>
<button ng:click="cancel()">Cancel</button>
<button ng:click="save()">Save</button>
</file>
<file name="welcome.html">
Hello {{person.name}},
<div>
Your contact information:
<div ng:repeat="contact in person.contacts">{{contact.type}}:
<span ng-bind-html="contact.url|linky"></span>
</div>
</div>
</file>
<file name="scenario.js">
it('should navigate to URL', function() {
element('a:contains(Welcome)').click();
expect(element('[ng-view]').text()).toMatch(/Hello anonymous/);
element('a:contains(Settings)').click();
input('form.name').enter('yourname');
element(':button:contains(Save)').click();
element('a:contains(Welcome)').click();
expect(element('[ng-view]').text()).toMatch(/Hello yourname/);
});
</file>
</example>
# Things to notice
* Routes are defined in the `AppCntl` class. The initialization of the controller causes the
initialization of the {@link api/ngRoute.$route $route} service with the proper URL
routes.
* The {@link api/ngRoute.$route $route} service then watches the URL and instantiates the
appropriate controller when the URL changes.
* The {@link api/ngRoute.directive:ngView ngView} widget loads the
view when the URL changes. It also sets the view scope to the newly instantiated controller.
* Changing the URL is sufficient to change the controller and view. It makes no difference whether
the URL is changed programmatically or by the user.

View file

@ -1,114 +0,0 @@
@ngdoc overview
@name Cookbook: Form
@description
A web application's main purpose is to present and gather data. For this reason Angular strives
to make both of these operations trivial. This example shows off how you can build a simple form to
allow a user to enter data.
<doc:example>
<doc:source>
<script>
function FormController($scope) {
var user = $scope.user = {
name: 'John Smith',
address:{line1: '123 Main St.', city:'Anytown', state:'AA', zip:'12345'},
contacts:[{type:'phone', value:'1(234) 555-1212'}]
};
$scope.state = /^\w\w$/;
$scope.zip = /^\d\d\d\d\d$/;
$scope.addContact = function() {
user.contacts.push({type:'email', value:''});
};
$scope.removeContact = function(contact) {
for (var i = 0, ii = user.contacts.length; i < ii; i++) {
if (contact === user.contacts[i]) {
$scope.user.contacts.splice(i, 1);
}
}
};
}
</script>
<div ng-controller="FormController" class="example">
<label>Name:</label><br>
<input type="text" ng-model="user.name" required/> <br><br>
<label>Address:</label><br>
<input type="text" ng-model="user.address.line1" size="33" required> <br>
<input type="text" ng-model="user.address.city" size="12" required>,
<input type="text" ng-model="user.address.state"
ng-pattern="state" size="2" required>
<input type="text" ng-model="user.address.zip" size="5"
ng-pattern="zip" required><br><br>
<label>Phone:</label>
[ <a href="" ng-click="addContact()">add</a> ]
<div ng-repeat="contact in user.contacts">
<select ng-model="contact.type">
<option>email</option>
<option>phone</option>
<option>pager</option>
<option>IM</option>
</select>
<input type="text" ng-model="contact.value" required>
[ <a href="" ng-click="removeContact(contact)">X</a> ]
</div>
<hr/>
Debug View:
<pre>user={{user | json}}</pre>
</div>
</doc:source>
<doc:scenario>
it('should show debug', function() {
expect(binding('user')).toMatch(/John Smith/);
});
it('should add contact', function() {
using('.example').element('a:contains(add)').click();
using('.example div:last').input('contact.value').enter('you@example.org');
expect(binding('user')).toMatch(/\(234\) 555\-1212/);
expect(binding('user')).toMatch(/you@example.org/);
});
it('should remove contact', function() {
using('.example').element('a:contains(X)').click();
expect(binding('user')).not().toMatch(/\(234\) 555\-1212/);
});
it('should validate zip', function() {
expect(using('.example').
element(':input[ng\\:model="user.address.zip"]').
prop('className')).not().toMatch(/ng-invalid/);
using('.example').input('user.address.zip').enter('abc');
expect(using('.example').
element(':input[ng\\:model="user.address.zip"]').
prop('className')).toMatch(/ng-invalid/);
});
it('should validate state', function() {
expect(using('.example').element(':input[ng\\:model="user.address.state"]').prop('className'))
.not().toMatch(/ng-invalid/);
using('.example').input('user.address.state').enter('XXX');
expect(using('.example').element(':input[ng\\:model="user.address.state"]').prop('className'))
.toMatch(/ng-invalid/);
});
</doc:scenario>
</doc:example>
# Things to notice
* The user data model is initialized {@link api/ng.directive:ngController controller} and is
available in the {@link api/ng.$rootScope.Scope scope} with the initial data.
* For debugging purposes we have included a debug view of the model to better understand what
is going on.
* The {@link api/ng.directive:input input directives} simply refer
to the model and are data-bound.
* The inputs validate. (Try leaving them blank or entering non digits in the zip field)
* In your application you can simply read from or write to the model and the form will be updated.
* By clicking the 'add' link you are adding new items into the `user.contacts` array which are then
reflected in the view.

View file

@ -1,39 +0,0 @@
@ngdoc overview
@name Cookbook: Hello World
@description
<doc:example>
<doc:source>
<script>
function HelloCntl($scope) {
$scope.name = 'World';
}
</script>
<div ng-controller="HelloCntl">
Your name: <input type="text" ng-model="name"/>
<hr/>
Hello {{name || "World"}}!
</div>
</doc:source>
<doc:scenario>
it('should change the binding when user enters text', function() {
expect(binding('name')).toEqual('World');
input('name').enter('angular');
expect(binding('name')).toEqual('angular');
});
</doc:scenario>
</doc:example>
# Things to notice
Take a look through the source and note:
* The script tag that {@link guide/bootstrap bootstraps} the Angular environment.
* The text {@link api/ng.directive:input input form control} which is
bound to the greeting name text.
* There is no need for listener registration and event firing on change events.
* The implicit presence of the `name` variable which is in the root {@link api/ng.$rootScope.Scope scope}.
* The double curly brace `{{markup}}`, which binds the name variable to the greeting text.
* The concept of {@link guide/databinding data binding}, which reflects any
changes to the
input field in the greeting text.

View file

@ -1,58 +0,0 @@
@ngdoc overview
@name Cookbook
@description
Welcome to the Angular cookbook. Here we will show you typical uses of Angular by example.
# Hello World
{@link helloworld Hello World}: The simplest possible application that demonstrates the
classic Hello World!
# Basic Form
{@link form Basic Form}: Displaying forms to the user for editing is the bread and butter
of web applications. Angular makes forms easy through bidirectional data binding.
# Advanced Form
{@link advancedform Advanced Form}: Taking the form example to the next level and
providing advanced features such as dirty detection, form reverting and submit disabling if
validation errors exist.
# Model View Controller
{@link mvc MVC}: Tic-Tac-Toe: Model View Controller (MVC) is a time-tested design pattern
to separate the behavior (JavaScript controller) from the presentation (HTML view). This
separation aids in maintainability and testability of your project.
# Multi-page App and Deep Linking
{@link deeplinking Deep Linking}: An AJAX application never navigates away from the
first page it loads. Instead, it changes the DOM of its single page. Eliminating full-page reloads
is what makes AJAX apps responsive, but it creates a problem in that apps with a single URL
prevent you from emailing links to a particular screen within your application.
Deep linking tries to solve this by changing the URL anchor without reloading a page, thus
allowing you to send links to specific screens in your app.
# Services
{@link api/ng Services}: Services are long lived objects in your applications that are
available across controllers. A collection of useful services are pre-bundled with Angular but you
will likely add your own. Services are initialized using dependency injection, which resolves the
order of initialization. This safeguards you from the perils of global state (a common way to
implement long lived objects).
# External Resources
{@link buzz Resources}: Web applications must be able to communicate with the external
services to get and update data. Resources are the abstractions of external URLs which are
specially tailored to Angular data binding.

View file

@ -1,128 +0,0 @@
@ngdoc overview
@name Cookbook: MVC
@description
MVC allows for a clean and testable separation between the behavior (controller) and the view
(HTML template). A Controller is just a JavaScript class which is grafted onto the scope of the
view. This makes it very easy for the controller and the view to share the model.
The model is a set of objects and primitives that are referenced from the Scope ($scope) object.
This makes it very easy to test the controller in isolation since one can simply instantiate the
controller and test without a view, because there is no connection between the controller and the
view.
<doc:example>
<doc:source>
<script>
function TicTacToeCntl($scope, $location) {
$scope.cellStyle= {
'height': '20px',
'width': '20px',
'border': '1px solid black',
'text-align': 'center',
'vertical-align': 'middle',
'cursor': 'pointer'
};
$scope.reset = function() {
$scope.board = [
['', '', ''],
['', '', ''],
['', '', '']
];
$scope.nextMove = 'X';
$scope.winner = '';
setUrl();
};
$scope.dropPiece = function(row, col) {
if (!$scope.winner && !$scope.board[row][col]) {
$scope.board[row][col] = $scope.nextMove;
$scope.nextMove = $scope.nextMove == 'X' ? 'O' : 'X';
setUrl();
}
};
$scope.reset();
$scope.$watch(function() { return $location.search().board;}, readUrl);
function setUrl() {
var rows = [];
angular.forEach($scope.board, function(row) {
rows.push(row.join(','));
});
$location.search({board: rows.join(';') + '/' + $scope.nextMove});
}
function grade() {
var b = $scope.board;
$scope.winner =
row(0) || row(1) || row(2) ||
col(0) || col(1) || col(2) ||
diagonal(-1) || diagonal(1);
function row(row) { return same(b[row][0], b[row][1], b[row][2]);}
function col(col) { return same(b[0][col], b[1][col], b[2][col]);}
function diagonal(i) { return same(b[0][1-i], b[1][1], b[2][1+i]);}
function same(a, b, c) { return (a==b && b==c) ? a : '';};
}
function readUrl(value) {
if (value) {
value = value.split('/');
$scope.nextMove = value[1];
angular.forEach(value[0].split(';'), function(row, col){
$scope.board[col] = row.split(',');
});
grade();
}
}
}
</script>
<h3>Tic-Tac-Toe</h3>
<div ng-controller="TicTacToeCntl">
Next Player: {{nextMove}}
<div class="winner" ng-show="winner">Player {{winner}} has won!</div>
<table class="board">
<tr ng-repeat="row in board track by $index" style="height:15px;">
<td ng-repeat="cell in row track by $index" ng-style="cellStyle"
ng-click="dropPiece($parent.$index, $index)">{{cell}}</td>
</tr>
</table>
<button ng-click="reset()">reset board</button>
</div>
</doc:source>
<doc:scenario>
it('should play a game', function() {
piece(1, 1);
expect(binding('nextMove')).toEqual('O');
piece(3, 1);
expect(binding('nextMove')).toEqual('X');
piece(1, 2);
piece(3, 2);
piece(1, 3);
expect(element('.winner').text()).toEqual('Player X has won!');
});
function piece(row, col) {
element('.board tr:nth-child('+row+') td:nth-child('+col+')').click();
}
</doc:scenario>
</doc:example>
# Things to notice
* The controller is defined in JavaScript and has no reference to the rendering logic.
* The controller is instantiated by Angular and injected into the view.
* The controller can be instantiated in isolation (without a view) and the code will still execute.
This makes it very testable.
* The HTML view is a projection of the model. In the above example, the model is stored in the
board variable.
* All of the controller's properties (such as board and nextMove) are available to the view.
* Changing the model changes the view.
* The view can call any controller function.
* In this example, the `setUrl()` and `readUrl()` functions copy the game state to/from the URL's
hash so the browser's back button will undo game steps. See deep-linking. This example calls {@link
api/ng.$rootScope.Scope#methods_$watch $watch()} to set up a listener that invokes `readUrl()` when needed.

View file

@ -11,7 +11,7 @@ For these reasons binding to event handler attributes (all attributes that start
An example code that would allow XSS vulnerability by evaluating user input in the window context could look like this: An example code that would allow XSS vulnerability by evaluating user input in the window context could look like this:
``` ```
<input ng-mode="username"> <input ng-model="username">
<div onclick="{{username}}">click me</div> <div onclick="{{username}}">click me</div>
``` ```

View file

@ -6,4 +6,5 @@
This error occurs in browsers that do not support XmlHttpRequest. AngularJS This error occurs in browsers that do not support XmlHttpRequest. AngularJS
supports Safari, Chrome, Firefox, Opera, IE8 and higher, and mobile browsers supports Safari, Chrome, Firefox, Opera, IE8 and higher, and mobile browsers
(Android, Chrome Mobile, iOS Safari). To avoid this error, use an officially (Android, Chrome Mobile, iOS Safari). To avoid this error, use an officially
supported browser. supported browser.

View file

@ -4,4 +4,4 @@
@description @description
This error occurs when 'ngPattern' is passed an expression that isn't a regular expression or doesn't have the expected format. 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.

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> <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: 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:

View file

@ -3,9 +3,9 @@
@fullName Orphan ngTransclude Directive @fullName Orphan ngTransclude Directive
@description @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. To resolve, either remove the offending `ngTransclude` or check that `transclude: true` is included in the intended directive definition.

View file

@ -21,19 +21,19 @@ Below is a quick example of animations being enabled for `ngShow` and `ngHide`:
<label> <label>
<input type="checkbox" ng-model="checked" style="float:left; margin-right:10px;"> Is Visible... <input type="checkbox" ng-model="checked" style="float:left; margin-right:10px;"> Is Visible...
</label> </label>
<div class="check-element animate-show-hide" ng-show="checked" style="clear:both;"> <div class="check-element sample-show-hide" ng-show="checked" style="clear:both;">
Visible... Visible...
</div> </div>
</div> </div>
</file> </file>
<file name="animations.css"> <file name="animations.css">
.animate-show-hide { .sample-show-hide {
padding:10px; padding:10px;
border:1px solid black; border:1px solid black;
background:white; background:white;
} }
.animate-show-hide.ng-hide-add, .animate-show-hide.ng-hide-remove { .sample-show-hide.ng-hide-add, .sample-show-hide.ng-hide-remove {
-webkit-transition:all linear 0.5s; -webkit-transition:all linear 0.5s;
-moz-transition:all linear 0.5s; -moz-transition:all linear 0.5s;
-o-transition:all linear 0.5s; -o-transition:all linear 0.5s;
@ -41,13 +41,13 @@ Below is a quick example of animations being enabled for `ngShow` and `ngHide`:
display:block!important; display:block!important;
} }
.animate-show-hide.ng-hide-add.ng-hide-add-active, .sample-show-hide.ng-hide-add.ng-hide-add-active,
.animate-show-hide.ng-hide-remove { .sample-show-hide.ng-hide-remove {
opacity:0; opacity:0;
} }
.animate-show-hide.ng-hide-add, .sample-show-hide.ng-hide-add,
.animate-show-hide.ng-hide-remove.ng-hide-remove-active { .sample-show-hide.ng-hide-remove.ng-hide-remove-active {
opacity:1; opacity:1;
} }
</file> </file>
@ -258,7 +258,7 @@ The table below explains in detail which animation events are triggered
| {@link api/ng.directive:ngInclude#usage_animations ngInclude} | enter and leave | | {@link api/ng.directive:ngInclude#usage_animations ngInclude} | enter and leave |
| {@link api/ng.directive:ngSwitch#usage_animations ngSwitch} | enter and leave | | {@link api/ng.directive:ngSwitch#usage_animations ngSwitch} | enter and leave |
| {@link api/ng.directive:ngIf#usage_animations ngIf} | enter and leave | | {@link api/ng.directive:ngIf#usage_animations ngIf} | enter and leave |
| {@link api/ng.directive:ngShow#usage_animations ngClass or &#123;&#123;class&#125;&#125;} | add and remove | | {@link api/ng.directive:ngClass#usage_animations ngClass or &#123;&#123;class&#125;&#125;} | add and remove |
| {@link api/ng.directive:ngShow#usage_animations ngShow & ngHide} | add and remove (the ng-hide class value) | | {@link api/ng.directive:ngShow#usage_animations ngShow & ngHide} | add and remove (the ng-hide class value) |
For a full breakdown of the steps involved during each animation event, refer to the {@link api/ngAnimate.$animate API docs}. For a full breakdown of the steps involved during each animation event, refer to the {@link api/ngAnimate.$animate API docs}.

View file

@ -190,6 +190,7 @@ This should help give you an idea of what Angular does internally.
<pre> <pre>
var $compile = ...; // injected into your code var $compile = ...; // injected into your code
var scope = ...; var scope = ...;
var parent = ...; // DOM element where the compiled template can be appended
var html = '<div ng-bind="exp"></div>'; var html = '<div ng-bind="exp"></div>';
@ -200,7 +201,10 @@ This should help give you an idea of what Angular does internally.
var linkFn = $compile(template); var linkFn = $compile(template);
// Step 3: link the compiled template with the scope. // Step 3: link the compiled template with the scope.
linkFn(scope); var element = linkFn(scope);
// Step 4: Append to DOM (optional)
parent.appendChild(element);
</pre> </pre>
### The difference between Compile and Link ### The difference between Compile and Link

View file

@ -184,7 +184,7 @@ The following graphic shows how everything works together after we introduced th
# View independent business logic: Services # View independent business logic: Services
Right now, the `InvoiceController` contains all logic of our example. When the application grows it 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 <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 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. from the web, e.g. by calling the Yahoo Finance API, without changing the controller.
@ -270,10 +270,10 @@ When Angular starts, it will use the configuration of the module with the name d
including the configuration of all modules that this module depends on. including the configuration of all modules that this module depends on.
In the example above: In the example above:
The template contains the directive `ng-app="invoice"`. This tells Angular The template contains the directive `ng-app="invoice2"`. This tells Angular
to use the `invoice` module as the main module for the application. to use the `invoice` module as the main module for the application.
The code snippet `angular.module('invoice', ['finance'])` specifies that the `invoice` module depends on the The code snippet `angular.module('invoice2', ['finance2'])` specifies that the `invoice2` module depends on the
`finance` module. By this, Angular uses the `InvoiceController` as well as the `currencyConverter` service. `finance2` module. By this, Angular uses the `InvoiceController` as well as the `currencyConverter` service.
Now that Angular knows of all the parts of the application, it needs to create them. Now that Angular knows of all the parts of the application, it needs to create them.
In the previous section we saw that controllers are created using a factory function. In the previous section we saw that controllers are created using a factory function.

View file

@ -168,7 +168,7 @@ starts with capital letter and ends with "Ctrl" or "Controller".
- Assigning a property to `$scope` creates or updates the model. - Assigning a property to `$scope` creates or updates the model.
- Controller methods can be created through direct assignment to scope (see the `chiliSpicy` method) - Controller methods can be created through direct assignment to scope (see the `chiliSpicy` method)
- The Controller methods and properties are available in the template (for the `<div>` element and - The Controller methods and properties are available in the template (for the `<div>` element and
and its children). its children).
## Spicy Arguments Example ## Spicy Arguments Example

View file

@ -19,7 +19,7 @@ testable.
To register a service, you must have a module that this service will be part of. Afterwards, you 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 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 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: Using the angular.Module api:
<pre> <pre>

View file

@ -53,18 +53,19 @@ function myController(scope, notifyService) {
myController.$inject = ['$scope','notify']; myController.$inject = ['$scope','notify'];
</script> </script>
<div ng-controller="myController"> <div id="simple" ng-controller="myController">
<p>Let's try this simple notify service, injected into the controller...</p> <p>Let's try this simple notify service, injected into the controller...</p>
<input ng-init="message='test'" ng-model="message" > <input ng-init="message='test'" ng-model="message" >
<button ng-click="callNotify(message);">NOTIFY</button> <button ng-click="callNotify(message);">NOTIFY</button>
<p>(you have to click 3 times to see an alert)</p> <p>(you have to click 3 times to see an alert)</p>
</div> </div>
</doc:source> </doc:source>
<doc:scenario> <doc:protractor>
it('should test service', function() { it('should test service', function() {
expect(element(':input[ng\\:model="message"]').val()).toEqual('test'); expect(element(by.id('simple')).element(by.model('message')).getAttribute('value'))
.toEqual('test');
}); });
</doc:scenario> </doc:protractor>
</doc:example> </doc:example>
## Implicit Dependency Injection ## Implicit Dependency Injection
@ -95,7 +96,7 @@ function myController($scope, notify) {
}; };
} }
</script> </script>
<div ng-controller="myController"> <div id="implicit" ng-controller="myController">
<p>Let's try the notify service, that is implicitly injected into the controller...</p> <p>Let's try the notify service, that is implicitly injected into the controller...</p>
<input ng-init="message='test'" ng-model="message"> <input ng-init="message='test'" ng-model="message">
<button ng-click="callNotify(message);">NOTIFY</button> <button ng-click="callNotify(message);">NOTIFY</button>

View file

@ -50,19 +50,18 @@ of which depend on other services that are provided by the Angular framework:
* @param {*} message Message to be logged. * @param {*} message Message to be logged.
*/ */
function batchLogModule($provide){ function batchLogModule($provide){
$provide.factory('batchLog', ['$timeout', '$log', function($timeout, $log) { $provide.factory('batchLog', ['$interval', '$log', function($interval, $log) {
var messageQueue = []; var messageQueue = [];
function log() { function log() {
if (messageQueue.length) { if (messageQueue.length) {
$log('batchLog messages: ', messageQueue); $log.log('batchLog messages: ', messageQueue);
messageQueue = []; messageQueue = [];
} }
$timeout(log, 50000);
} }
// start periodic checking // start periodic checking
log(); $interval(log, 50000);
return function(message) { return function(message) {
messageQueue.push(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'); angular.injector([batchLogModule]).get('routeTemplateMonitor');
</pre> </pre>
Things to notice in this example: 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 {@link api/ng.$log $log} services, and allows messages to be logged into the
`console.log` in batches. `console.log` in batches.
* The `routeTemplateMonitor` service depends on the built-in {@link api/ngRoute.$route * The `routeTemplateMonitor` service depends on the built-in {@link api/ngRoute.$route

View file

@ -13,7 +13,7 @@ Angular sets these CSS classes. It is up to your application to provide useful s
* `ng-binding` * `ng-binding`
- **Usage:** angular applies this class to any element that is attached to a data binding, via `ng-bind` or - **Usage:** angular applies this class to any element that is attached to a data binding, via `ng-bind` or
{{}} curly braces, for example. (see {@link guide/databinding databinding} guide) `{{}}` curly braces, for example. (see {@link guide/databinding databinding} guide)
* `ng-invalid`, `ng-valid` * `ng-invalid`, `ng-valid`
- **Usage:** angular applies this class to an input widget element if that element's input does - **Usage:** angular applies this class to an input widget element if that element's input does

View file

@ -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 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 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 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: The class above is testable, since in the test we can write:
<pre> <pre>
@ -222,7 +222,7 @@ var pc = new PasswordCtrl();
input.val('abc'); input.val('abc');
pc.grade(); pc.grade();
expect(span.text()).toEqual('weak'); expect(span.text()).toEqual('weak');
$('body').html(''); $('body').empty();
</pre> </pre>
In angular the controllers are strictly separated from the DOM manipulation logic and this results in In angular the controllers are strictly separated from the DOM manipulation logic and this results in

View file

@ -146,7 +146,7 @@ of service names to inject.
var MyController = function(renamed$scope, renamedGreeter) { var MyController = function(renamed$scope, renamedGreeter) {
... ...
} }
MyController.$inject = ['$scope', 'greeter']; MyController['$inject'] = ['$scope', 'greeter'];
</pre> </pre>
In this scenario the ordering of the values in the '$inject' array must match the ordering of the arguments to inject. In this scenario the ordering of the values in the '$inject' array must match the ordering of the arguments to inject.

View file

@ -55,7 +55,7 @@ The following also **matches** `ngModel`:
Angular **normalizes** an element's tag and attribute name to determine which elements match which Angular **normalizes** an element's tag and attribute name to determine which elements match which
directives. We typically refer to directives by their case-sensitive directives. We typically refer to directives by their case-sensitive
{@link http://en.wikipedia.org/wiki/CamelCase camelCase} **normalized** name (e.g. `ngModel`). {@link http://en.wikipedia.org/wiki/CamelCase camelCase} **normalized** name (e.g. `ngModel`).
However, since HTML is case-insensitive, we refer to directives in the DOM by lower-case However, since HTML is case-insensitive, we refer to directives in the DOM by lower-case
forms, typically using {@link http://en.wikipedia.org/wiki/Letter_case#Computers dash-delimited} forms, typically using {@link http://en.wikipedia.org/wiki/Letter_case#Computers dash-delimited}
attributes on DOM elements (e.g. `ng-model`). attributes on DOM elements (e.g. `ng-model`).
@ -84,10 +84,10 @@ Here are some equivalent examples of elements that match `ngBind`:
<span x-ng-bind="name"></span> <br/> <span x-ng-bind="name"></span> <br/>
</div> </div>
</file> </file>
<file name="scenario.js"> <file name="protractorTest.js">
it('should show off bindings', function() { it('should show off bindings', function() {
expect(element('div[ng-controller="Ctrl1"] span[ng-bind]').text()) expect(element(by.css('div[ng-controller="Ctrl1"] span[ng-bind]')).getText())
.toBe('Max Karl Ernst Ludwig Planck (April 23, 1858 October 4, 1947)'); .toBe('Max Karl Ernst Ludwig Planck (April 23, 1858 October 4, 1947)');
}); });
</file> </file>
</example> </example>
@ -174,9 +174,9 @@ For example, we could fix the example above by instead writing:
## Creating Directives ## Creating Directives
First let's talk about the API for registering directives. Much like controllers, directives are First let's talk about the {@link api/ng.$compileProvider#methods_directive API for registering directives}. Much like
registered on modules. To register a directive, you use the `module.directive` API. controllers, directives are registered on modules. To register a directive, you use the
`module.directive` takes the `module.directive` API. `module.directive` takes the
{@link guide/directive#creating-custom-directives_matching-directives normalized} directive name {@link guide/directive#creating-custom-directives_matching-directives normalized} directive name
followed by a **factory function.** This factory function should return an object with the different followed by a **factory function.** This factory function should return an object with the different
options to tell `$compile` how the directive should behave when matched. options to tell `$compile` how the directive should behave when matched.
@ -280,7 +280,7 @@ using `templateUrl` instead:
</example> </example>
Great! But what if we wanted to have our directive match the tag name `<my-customer>` instead? 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"> <div class="alert alert-waring">
**Note:** When you create a directive, it is restricted to attribute only by default. In order to **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"> <div class="alert alert-warning">
**Note:** Normally, a scope prototypically inherits from its parent. An isolated scope does not. **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>
<div class="alert alert-success"> <div class="alert alert-success">
@ -525,11 +527,14 @@ where:
* `scope` is an Angular scope object. * `scope` is an Angular scope object.
* `element` is the jqLite-wrapped element that this directive matches. * `element` is the jqLite-wrapped element that this directive matches.
* `attrs` is an object with the normalized attribute names and their corresponding values. * `attrs` is a hash object with key-value pairs of normalized attribute names and their
corresponding attribute values.
In our `link` function, we want to update the displayed time once a second, or whenever a user 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 changes the time formatting string that our directive binds to. We will use the `$interval` service
if the directive is deleted so we don't introduce a memory leak. 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"> <example module="docsTimeDirective">
<file name="script.js"> <file name="script.js">
@ -537,7 +542,7 @@ if the directive is deleted so we don't introduce a memory leak.
.controller('Ctrl2', function($scope) { .controller('Ctrl2', function($scope) {
$scope.format = 'M/d/yy h:mm:ss a'; $scope.format = 'M/d/yy h:mm:ss a';
}) })
.directive('myCurrentTime', function($timeout, dateFilter) { .directive('myCurrentTime', function($interval, dateFilter) {
function link(scope, element, attrs) { function link(scope, element, attrs) {
var format, var format,
@ -552,20 +557,14 @@ if the directive is deleted so we don't introduce a memory leak.
updateTime(); updateTime();
}); });
function scheduleUpdate() {
// save the timeoutId for canceling
timeoutId = $timeout(function() {
updateTime(); // update DOM
scheduleUpdate(); // schedule the next update
}, 1000);
}
element.on('$destroy', function() { element.on('$destroy', function() {
$timeout.cancel(timeoutId); $interval.cancel(timeoutId);
}); });
// start the UI update process. // start the UI update process; save the timeoutId for canceling
scheduleUpdate(); timeoutId = $interval(function() {
updateTime(); // update DOM
}, 1000);
} }
return { return {
@ -583,7 +582,7 @@ if the directive is deleted so we don't introduce a memory leak.
There are a couple of things to note here. There are a couple of things to note here.
Just like the `module.controller` API, the function argument in `module.directive` is dependency 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. function.
We register an event `element.on('$destroy', ...)`. What fires this `$destroy` event? We register an event `element.on('$destroy', ...)`. What fires this `$destroy` event?
@ -736,13 +735,13 @@ own behavior to it.
We want to run the function we pass by invoking it from the directive's scope, but have it run We want to run the function we pass by invoking it from the directive's scope, but have it run
in the context of the scope where its registered. in the context of the scope where its registered.
We saw earlier how to use `=prop` in the `scope` option, but in the above example, we're using We saw earlier how to use `=attr` in the `scope` option, but in the above example, we're using
`&prop` instead. `&` bindings expose a function to an isolated scope allowing the isolated scope `&attr` instead. `&` bindings expose a function to an isolated scope allowing the isolated scope
to invoke it, but maintaining the original scope of the function. So when a user clicks the to invoke it, but maintaining the original scope of the function. So when a user clicks the
`x` in the dialog, it runs `Ctrl`'s `close` function. `x` in the dialog, it runs `Ctrl`'s `hideDialog` function.
<div class="alert alert-success"> <div class="alert alert-success">
**Best Practice:** use `&prop` in the `scope` option when you want your directive **Best Practice:** use `&attr` in the `scope` option when you want your directive
to expose an API for binding to behaviors. to expose an API for binding to behaviors.
</div> </div>

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. 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: 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 evaluation, unlike in JavaScript where the expressions are evaluated against the global
`window`. `window`.
@ -37,11 +37,11 @@ JavaScript, use the {@link api/ng.$rootScope.Scope#methods_$eval `$eval()`} meth
<doc:source> <doc:source>
1+2={{1+2}} 1+2={{1+2}}
</doc:source> </doc:source>
<doc:scenario> <doc:protractor>
it('should calculate expression in binding', function() { it('should calculate expression in binding', function() {
expect(binding('1+2')).toEqual('3'); expect(element(by.binding('1+2')).getText()).toEqual('1+2=3');
}); });
</doc:scenario> </doc:protractor>
</doc:example> </doc:example>
You can try evaluating different expressions here: You can try evaluating different expressions here:
@ -73,14 +73,14 @@ You can try evaluating different expressions here:
</ul> </ul>
</div> </div>
</doc:source> </doc:source>
<doc:scenario> <doc:protractor>
it('should allow user expression testing', function() { it('should allow user expression testing', function() {
element('.expressions :button').click(); element(by.css('.expressions button')).click();
var li = using('.expressions ul').repeater('li'); var lis = element(by.css('.expressions ul')).element.all(by.repeater('expr in exprs'));
expect(li.count()).toBe(1); expect(lis.count()).toBe(1);
expect(li.row(0)).toEqual(["3*10|currency", "$30.00"]); expect(lis.get(0).getText()).toEqual('[ X ] 3*10|currency => $30.00');
}); });
</doc:scenario> </doc:protractor>
</doc:example> </doc:example>
@ -99,7 +99,7 @@ prevent accidental access to the global state (a common source of subtle bugs).
$scope.name = 'World'; $scope.name = 'World';
$scope.greet = function() { $scope.greet = function() {
($window.mockWindow || $window).alert('Hello ' + $scope.name); $window.alert('Hello ' + $scope.name);
} }
} }
</script> </script>
@ -108,21 +108,17 @@ prevent accidental access to the global state (a common source of subtle bugs).
<button ng-click="greet()">Greet</button> <button ng-click="greet()">Greet</button>
</div> </div>
</doc:source> </doc:source>
<doc:scenario> <doc:protractor>
it('should calculate expression in binding', function() { it('should calculate expression in binding', function() {
var alertText; element(by.css('[ng-click="greet()"]')).click();
this.addFutureAction('set mock', function($window, $document, done) {
$window.mockWindow = { var alertDialog = browser.switchTo().alert();
alert: function(text){ alertText = text; }
}; expect(alertDialog.getText()).toEqual('Hello World');
done();
}); alertDialog.accept();
element(':button:contains(Greet)').click(); });
expect(this.addFuture('alert text', function(done) { </doc:protractor>
done(null, alertText);
})).toBe('Hello World');
});
</doc:scenario>
</doc:example> </doc:example>
## Forgiving ## Forgiving

View file

@ -121,3 +121,6 @@ text upper-case.
</doc:source> </doc:source>
</doc:example> </doc:example>
## Testing custom filters
See the {@link http://docs.angularjs.org/tutorial/step_09#test phonecat tutorial} for an example.

View file

@ -33,10 +33,10 @@ In addition it provides an {@link api/ng.directive:ngModel.NgModelController API
<script> <script>
function Controller($scope) { function Controller($scope) {
$scope.master= {}; $scope.master = {};
$scope.update = function(user) { $scope.update = function(user) {
$scope.master= angular.copy(user); $scope.master = angular.copy(user);
}; };
$scope.reset = function() { $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}. 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. 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. Similarly, an input control that has the {@link api/ng.directive:ngModel ngModel} directive holds an
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. 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: This allows us to extend the above example with these features:
@ -230,7 +235,7 @@ In the following example we create two directives.
<script> <script>
var app = angular.module('form-example1', []); var app = angular.module('form-example1', []);
var INTEGER_REGEXP = /^\-?\d*$/; var INTEGER_REGEXP = /^\-?\d+$/;
app.directive('integer', function() { app.directive('integer', function() {
return { return {
require: 'ngModel', require: 'ngModel',

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 in other locales might use your app, you should provide your own currency symbol to make sure the
actual value is understood. 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. 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 browser will specify the locale as ja, and the balance of '¥1000.00' will be shown instead. This
will really upset your client. will really upset your client.

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: 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 [JSON2](https://github.com/douglascrockford/JSON-js) or
[JSON3](http://bestiejs.github.com/json3/) polyfills for this. [JSON3](http://bestiejs.github.com/json3/) polyfills for this.
<pre> <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 3. you **do not** use custom element tags such as `<ng:view>` (use the attribute version
`<div ng-view>` instead), or `<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> <pre>
<!doctype html> <!doctype html>
<html xmlns:ng="http://angularjs.org" id="ng-app" ng-app="optionalModuleName"> <html xmlns:ng="http://angularjs.org" id="ng-app" ng-app="optionalModuleName">

View file

@ -7,19 +7,14 @@
Everything you need to know about AngularJS Everything you need to know about AngularJS
* {@link guide/introduction What is AngularJS?} * {@link guide/introduction What is AngularJS?}
* {@link guide/concepts Conceptual Overview} * {@link guide/concepts Conceptual Overview}
## Tutorials ## Tutorials
* {@link tutorial/index Official AngularJS Tutorial} * {@link tutorial/index Official AngularJS Tutorial}
* [10 Reasons Why You Should Use AngularJS](http://www.sitepoint.com/10-reasons-use-angularjs/) * [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) * [Design Principles of AngularJS (video)](https://www.youtube.com/watch?v=HCR7i5F5L8c)
* [Fundamentals in 60 Minutes (video)](http://www.youtube.com/watch?v=i9MHigUZKEM) * [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) * [For folks with jQuery background](http://stackoverflow.com/questions/14994391/how-do-i-think-in-angularjs-if-i-have-a-jquery-background)
## Core Concepts ## 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. 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/databinding Data binding}
* {@link guide/expression Expressions} * {@link guide/expression Expressions}
* {@link guide/directive Directives} * {@link guide/directive Directives}
* {@link api/ngRoute.$route Views and routes (see the example)} * {@link api/ngRoute.$route Views and routes (see the example)}
* {@link guide/filter Filters} * {@link guide/filter Filters}
* {@link guide/forms Forms} and [Concepts of AngularJS Forms](http://mrbool.com/the-concepts-of-angularjs-forms/29117) * {@link guide/forms Forms} and [Concepts of AngularJS Forms](http://mrbool.com/the-concepts-of-angularjs-forms/29117)
### Application Structure ### Application Structure
* **Blog post: **[When to use directives, controllers or services](http://kirkbushell.me/when-to-use-directives-controllers-or-services-in-angular/) * **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} * **App wiring:** {@link guide/di Dependency injection}
* **Exposing model to templates:** {@link guide/scope Scopes} * **Exposing model to templates:** {@link guide/scope Scopes}
* **Communicating with servers:** {@link api/ng.$http $http}, {@link api/ngResource.$resource $resource} * **Communicating with servers:** {@link api/ng.$http $http}, {@link api/ngResource.$resource $resource}
### Other AngularJS Features ### 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) * **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) * **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/) * **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} * **Mobile:** {@link api/ngTouch Touch events}
### Testing ### 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/) * **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) * **Scenario testing:** [Protractor](https://github.com/angular/protractor)
## Specific Topics ## 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/) * **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/) * **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) * **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) * **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) * **Visualization:** [SVG](http://gaslight.co/blog/angular-backed-svgs), [D3.js](http://www.ng-newsletter.com/posts/d3-on-angular.html)
## Tools ## Tools
* **Debugging:** [Batarang](https://chrome.google.com/webstore/detail/angularjs-batarang/ighdmehidhipcmcojjgiloacoafjmpfk?hl=en) * **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) * **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) * **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/) * **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 ## 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/). 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/) * **Internationalization:** [angular-translate](http://pascalprecht.github.io/angular-translate/), [angular-gettext](http://angular-gettext.rocketeer.be/)
* **RESTful services:** [Restangular](https://github.com/mgonto/restangular) * **RESTful services:** [Restangular](https://github.com/mgonto/restangular)
* **SQL and NoSQL backends:** [BreezeJS](http://www.breezejs.com/), [AngularFire](http://angularfire.com/) * **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/) * **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 ## 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) * **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) * **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/) * **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 ### 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) * **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) * **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) * **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/) * **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) * **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) * **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) * **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 ## 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 * [ng-book: The Complete Book on AngularJS](http://ng-book.com/) by Ari Lerner
###Videos: ###Videos:
* [egghead.io](http://egghead.io/), * [egghead.io](http://egghead.io/)
* [Angular on YouTube](http://youtube.com/angularjs) * [Angular on YouTube](http://youtube.com/angularjs)
###Courses ### Courses
* **Free on-line:** * **Free online:**
[thinkster.io](http://thinkster.io), [thinkster.io](http://thinkster.io),
[CodeAcademy](http://www.codecademy.com/courses/javascript-advanced-en-2hJ3J/0/1) [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), [Pluralsite (3 courses)](http://www.pluralsight.com/training/Courses/Find?highlight=true&searchTerm=angularjs),
[Tuts+](https://tutsplus.com/course/easier-js-apps-with-angular/), [Tuts+](https://tutsplus.com/course/easier-js-apps-with-angular/),
[lynda.com](http://www.lynda.com/AngularJS-tutorials/Up-Running-AngularJS/133318-2.html) [lynda.com](http://www.lynda.com/AngularJS-tutorials/Up-Running-AngularJS/133318-2.html)
* **Paid on-site:** * **Paid onsite:**
[angularbootcamp.com](http://angularbootcamp.com/) [angularbootcamp.com](http://angularbootcamp.com/)
## Getting Help ## 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: 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) * [Stackoverflow.com](http://stackoverflow.com/search?q=angularjs)
* [AngularJS mailing list](https://groups.google.com/forum/#!forum/angular) * [AngularJS mailing list](https://groups.google.com/forum/#!forum/angular)
* [AngularJS IRC channel](http://webchat.freenode.net/?channels=angularjs&uio=d4) * [AngularJS IRC channel](http://webchat.freenode.net/?channels=angularjs&uio=d4)
## Social Channels ## Social Channels
* **Daily updates:** [Google+](https://plus.google.com/u/0/+AngularJS) or [Twitter](https://twitter.com/angularjs) * **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/) * **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) * **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/) * **Official news and releases: **[AngularJS Blog](http://blog.angularjs.org/)
## Contributing to AngularJS ## Contributing to AngularJS

View file

@ -590,6 +590,10 @@ See [79223eae](https://github.com/angular/angular.js/commit/79223eae502283889334
## Underscore-prefixed/suffixed properties are non-bindable ## Underscore-prefixed/suffixed properties are non-bindable
<div class="alert alert-info">
<p>**Reverted**: This breaking change has been reverted in 1.2.1, and so can be ignored if you're using **version 1.2.1 or higher**</p>
</div>
This change introduces the notion of "private" properties (properties This change introduces the notion of "private" properties (properties
whose names begin and/or end with an underscore) on the scope chain. whose names begin and/or end with an underscore) on the scope chain.
These properties will not be available to Angular expressions (i.e. {{ These properties will not be available to Angular expressions (i.e. {{

View file

@ -110,7 +110,7 @@ myApp.factory('clientId', function clientIdFactory() {
But given that the token is just a string literal, sticking with the Value recipe is still more But given that the token is just a string literal, sticking with the Value recipe is still more
appropriate as it makes the code easier to follow. appropriate as it makes the code easier to follow.
Let's say, however, that we would also like create a service that computes a token used for Let's say, however, that we would also like to create a service that computes a token used for
authentication against a remote API. This token will be called 'apiToken' and will be computed authentication against a remote API. This token will be called 'apiToken' and will be computed
based on the `clientId` value and a secret stored in browser's local storage: based on the `clientId` value and a secret stored in browser's local storage:

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 propagate any model changes through the system into the view from outside of the "Angular
realm" (controllers, services, Angular event handlers). realm" (controllers, services, Angular event handlers).
- Scopes can be nested to isolate application components while providing access to shared model - Scopes can be nested to limit access to the properties of application components while providing
properties. A scope (prototypically) inherits properties from its parent scope. 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 - Scopes provide context against which {@link guide/expression expressions} are evaluated. For
example `{{username}}` expression is meaningless, unless it is evaluated against a specific example `{{username}}` expression is meaningless, unless it is evaluated against a specific
@ -177,7 +181,7 @@ To examine the scope in the debugger:
2. The debugger allows you to access the currently selected element in the console as `$0` 2. The debugger allows you to access the currently selected element in the console as `$0`
variable. variable.
3. To retrieve the associated scope in console execute: `angular.element($0).scope()` 3. To retrieve the associated scope in console execute: `angular.element($0).scope()` or just type $scope
## Scope Events Propagation ## Scope Events Propagation
@ -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 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 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, 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 or asynchronous work with {@link api/ng.$http $http}, {@link api/ng.$timeout $timeout}
api/ng.$timeout $timeout} services. or {@link api/ng.$interval $interval} services.
4. **Mutation observation** 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 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 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. 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 ### Controllers and Scopes

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 Before you can build AngularJS, you must install and configure the following dependencies on your
machine: 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. Installing Git} is a good source of information.
* {@link http://nodejs.org Node.js}: We use Node to generate the documentation, run a * {@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 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 ## Forking Angular on Github
@ -85,6 +87,16 @@ grunt package
Administrator). This is because `grunt package` creates some symbolic links. Administrator). This is because `grunt package` creates some symbolic links.
</div> </div>
<div class="alert alert-warning">
**Note:** If you're using Linux, and npm install fails with the message
'Please try running this command again as root/Administrator.', you may need to globally install grunt and bower:
<ul>
<li>sudo npm install -g grunt-cli</li>
<li>sudo npm install -g bower</li>
</ul>
</div>
The build output can be located under the `build` directory. It consists of the following files and The build output can be located under the `build` directory. It consists of the following files and
directories: directories:

View file

@ -73,12 +73,11 @@ directory.</p></li>
<p>Additionally install <a href="http://karma-runner.github.io/">Karma</a> and its plugins if you <p>Additionally install <a href="http://karma-runner.github.io/">Karma</a> and its plugins if you
don't have it already:</p> don't have it already:</p>
<pre> <pre>
npm install -g karma
npm install npm install
</pre></li> </pre></li>
<li><p>You will need an http server running on your system. Mac and Linux machines typically <li><p>You will need an http server running on your system. Mac and Linux machines typically
have Apache pre-installed, but If you don't already have one installed, you can use <code>node</code> have Apache pre-installed, but If you don't already have one installed, you can use <code>node</code>
to run <code>scripts/web-server.js</code>, a simple bundled http server.</p></li> to run a simple bundled http server: <code>node scripts/web-server.js</code>.</p></li>
</ol> </ol>
</div> </div>
@ -107,8 +106,8 @@ directory.</p>
<p>Other commands like <code>test.bat</code> or <code>e2e-test.bat</code> should be <p>Other commands like <code>test.bat</code> or <code>e2e-test.bat</code> should be
executed from the Windows command line.</li> executed from the Windows command line.</li>
<li><p>You need an http server running on your system, but if you don't already have one <li><p>You need an http server running on your system, but if you don't already have one
already installed, you can use <code>node</code> to run <code>scripts\web-server.js</code>, a simple already installed, you can use <code>node</code> to run a simple
bundled http server.</p></li> bundled http server: <code>node scripts\web-server.js</code>.</p></li>
</ol> </ol>
</div> </div>

View file

@ -26,7 +26,7 @@ angular-seed, and run the application in the browser.
<ol> <ol>
<li>In a <i>separate</i> terminal tab or window, run <code>node ./scripts/web-server.js</code> to start the web server.</li> <li>In a <i>separate</i> terminal tab or window, run <code>node ./scripts/web-server.js</code> to start the web server.</li>
<li>Open a browser window for the app and navigate to <a <li>Open a browser window for the app and navigate to <a
href="http://localhost:8000/app/index.html">http://localhost:8000/app/index.html</a></li> href="http://localhost:8000/app/index.html" target="_blank">`http://localhost:8000/app/index.html`</a></li>
</ol> </ol>
</li> </li>
<li><b>For other http servers:</b> <li><b>For other http servers:</b>
@ -54,7 +54,7 @@ angular-seed, and run the application in the browser.
<li><b>For node.js users:</b> <li><b>For node.js users:</b>
<ol> <ol>
<li>In a <i>separate</i> terminal tab or window, run <code>node scripts\web-server.js</code> to start the web server.</li> <li>In a <i>separate</i> terminal tab or window, run <code>node scripts\web-server.js</code> to start the web server.</li>
<li>Open a browser window for the app and navigate to <a href="http://localhost:8000/app/index.html">http://localhost:8000/app/index.html</a></li> <li>Open a browser window for the app and navigate to <a href="http://localhost:8000/app/index.html" target="_blank">`http://localhost:8000/app/index.html`</a></li>
</ol> </ol>
</li> </li>
<li><b>For other http servers:</b> <li><b>For other http servers:</b>
@ -73,7 +73,7 @@ angular-seed, and run the application in the browser.
You can now see the page in your browser. It's not very exciting, but that's OK. You can now see the page in your browser. It's not very exciting, but that's OK.
The HTML page that displays "Nothing here yet!" was constructed with the HTML code shown below. The HTML page that displays "Nothing here yet!" was constructed with the HTML code shown below.
The code contains some key Angular elements that we will need going forward. The code contains some key Angular elements that we will need as we progress.
__`app/index.html`:__ __`app/index.html`:__
<pre> <pre>
@ -104,7 +104,7 @@ __`app/index.html`:__
The `ng-app` attribute represents an Angular directive named `ngApp` (Angular uses The `ng-app` attribute represents an Angular directive named `ngApp` (Angular uses
`name-with-dashes` for its custom attributes and `camelCase` for the corresponding directives `name-with-dashes` for its custom attributes and `camelCase` for the corresponding directives
that implements them). which implement them).
This directive is used to flag the html element that Angular should consider to be the root element This directive is used to flag the html element that Angular should consider to be the root element
of our application. of our application.
This gives application developers the freedom to tell Angular if the entire html page or only a This gives application developers the freedom to tell Angular if the entire html page or only a
@ -179,7 +179,7 @@ For the purposes of this tutorial, we modified the angular-seed with the followi
* Removed the example app * Removed the example app
* Added phone images to `app/img/phones/` * Added phone images to `app/img/phones/`
* Added phone data files (JSON) to `app/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/`

View file

@ -184,11 +184,15 @@ http://pivotal.github.com/jasmine/ Jasmine home page} and at the {@link
http://pivotal.github.io/jasmine/ Jasmine docs}. http://pivotal.github.io/jasmine/ Jasmine docs}.
The angular-seed project is pre-configured to run all unit tests using {@link The angular-seed project is pre-configured to run all unit tests using {@link
http://karma-runner.github.io/ Karma}. To run the test, do the following: http://karma-runner.github.io/ Karma}. Ensure that the necessary karma plugins are installed.
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 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 `./scripts/test.sh` (if you are on Windows, run scripts\test.bat) to start the Karma server (the
is located at `./config/karma.conf.js`). 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 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. the background. Karma will use this browser for test execution.
@ -202,7 +206,7 @@ is located at `./config/karma.conf.js`).
Yay! The test passed! Or not... 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? and will rerun the tests for you. Now isn't that sweet?
# Experiments # Experiments
@ -213,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: * 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: * Create a repeater that constructs a simple table:

View file

@ -127,8 +127,8 @@ end-to-end tests! Use `./scripts/e2e-test.sh` script for that. End-to-end tests
with unit tests, Karma will exit after the test run and will not automatically rerun the test with unit tests, Karma will exit after the test run and will not automatically rerun the test
suite on every file change. To rerun the test suite, execute the `e2e-test.sh` script again. suite on every file change. To rerun the test suite, execute the `e2e-test.sh` script again.
Note: You must ensure you've installed karma-ng-scenario prior to running the `e2e-test.sh` script. Note: You must ensure you've installed the karma-ng-scenario framework plugin prior to running the
You can do this by issuing `npm install karma-ng-scenario` into your terminal. `e2e-test.sh` script. You can do this by issuing `npm install` into your terminal.
This test verifies that the search box and the repeater are correctly wired together. Notice how This test verifies that the search box and the repeater are correctly wired together. Notice how
easy it is to write end-to-end tests in Angular. Although this example is for a simple test, it easy it is to write end-to-end tests in Angular. Although this example is for a simple test, it
@ -154,7 +154,7 @@ really is that easy to set up any functional, readable, end-to-end test.
`ngController` declaration to the HTML element because it is the common parent of both the body `ngController` declaration to the HTML element because it is the common parent of both the body
and title elements: and title elements:
<html ng-app ng-controller="PhoneListCtrl"> <html ng-app="phonecatApp" ng-controller="PhoneListCtrl">
Be sure to __remove__ the `ng-controller` declaration from the body element. Be sure to __remove__ the `ng-controller` declaration from the body element.

View file

@ -88,8 +88,8 @@ phonecatApp.controller('PhoneListCtrl', function ($scope) {
record. This property is used to order phones by age. 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 * 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 not set a default value here, the `orderBy` filter would remain uninitialized until our
option from the drop down menu. 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 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'` browser, "Newest" is selected in the drop down menu. This is because we set `orderProp` to `'age'`

View file

@ -170,6 +170,9 @@ describe('PhoneCat controllers', function() {
describe('PhoneListCtrl', function(){ describe('PhoneListCtrl', function(){
var scope, ctrl, $httpBackend; 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_). // 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 // This allows us to inject a service but then attach it to a variable
// with the same name as the service. // 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 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. and the created scope as parameters.
Because our code now uses the `$http` service to fetch the phone list data in our controller, before Because our code now uses the `$http` service to fetch the phone list data in our controller, before

View file

@ -64,7 +64,7 @@ We also added phone images next to each record using an image tag with the {@lin
api/ng.directive:ngSrc ngSrc} directive. That directive prevents the api/ng.directive:ngSrc ngSrc} directive. That directive prevents the
browser from treating the angular `{{ expression }}` markup literally, and initiating a request to browser from treating the angular `{{ expression }}` markup literally, and initiating a request to
invalid url `http://localhost:8000/app/{{phone.imageUrl}}`, which it would have done if we had only invalid url `http://localhost:8000/app/{{phone.imageUrl}}`, which it would have done if we had only
specified an attribute binding in a regular `src` attribute (`<img class="diagram" src="{{phone.imageUrl}}">`). specified an attribute binding in a regular `src` attribute (`<img src="{{phone.imageUrl}}">`).
Using the `ngSrc` directive prevents the browser from making an http request to an invalid location. Using the `ngSrc` directive prevents the browser from making an http request to an invalid location.

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, 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. 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. address doesn't match either of our routes.
Note the use of the `:phoneId` parameter in the second route declaration. The `$route` service uses Note the use of the `:phoneId` parameter in the second route declaration. The `$route` service uses
@ -177,7 +177,7 @@ route into the layout template. This makes it a perfect fit for our `index.html`
<div class="alert alert-info"> <div class="alert alert-info">
**Note:** Starting with AngularJS version 1.2, `ngRoute` is in its own module and must be loaded by loading **Note:** Starting with AngularJS version 1.2, `ngRoute` is in its own module and must be loaded by loading
the `angular-route.js` file distributed with Angular. The easist way to load the file is to add a `<script>` the `angular-route.js` file distributed with Angular. The easiest way to load the file is to add a `<script>`
tag to your `index.html` file as shown below. tag to your `index.html` file as shown below.
</div> </div>
@ -258,7 +258,7 @@ to various URLs and verify that the correct view was rendered.
<pre> <pre>
... ...
it('should redirect index.html to index.html#/phones', function() { 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'); 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() { describe('Phone detail view', function() {
beforeEach(function() { beforeEach(function() {
browser().navigateTo('../../app/index.html#/phones/nexus-s'); browser().navigateTo('app/index.html#/phones/nexus-s');
}); });

View file

@ -120,7 +120,7 @@ Angular's server}.
<button ng-click="hello('Elmo')">Hello</button> <button ng-click="hello('Elmo')">Hello</button>
to the `phone-details.html` template. to the `phone-detail.html` template.
<div style="display: none"> <div style="display: none">
TODO! TODO!

View file

@ -11,7 +11,7 @@ In this step, you will improve the way our app fetches data.
<div doc-tutorial-reset="11"></div> <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 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 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. api/ng.$http $http} API, HTTP methods and URLs.
@ -185,7 +185,7 @@ describe('PhoneCat controllers', function() {
xyzPhoneData = function() { xyzPhoneData = function() {
return { return {
name: 'phone xyz', name: 'phone xyz',
images: ['image/url1.png', 'image/url2.png'] images: ['image/url1.png', 'image/url2.png']
} }
}; };

View file

@ -43,7 +43,7 @@ __`app/index.html`.__
<pre> <pre>
... ...
<!-- jQuery is used for JavaScript animations (include this before angular.js) --> <!-- jQuery is used for JavaScript animations (include this before angular.js) -->
<script src="http://code.jquery.com/jquery-2.0.3.min.js"></script> <script src="http://code.jquery.com/jquery-1.10.2.min.js"></script>
<!-- required module to enable animation support in AngularJS --> <!-- required module to enable animation support in AngularJS -->
<script src="lib/angular/angular-animate.js"></script> <script src="lib/angular/angular-animate.js"></script>
@ -56,6 +56,10 @@ __`app/index.html`.__
... ...
</pre> </pre>
<div class="alert alert-error">
**Important:** Be sure to use jQuery version `1.10.x`. AngularJS does not yet support jQuery `2.x`.
</div>
Animations can now be created within the CSS code (`animations.css`) as well as the JavaScript code (`animations.js`). Animations can now be created within the CSS code (`animations.css`) as well as the JavaScript code (`animations.js`).
But before we start, let's create a new module which uses the ngAnimate module as a dependency just like we did before But before we start, let's create a new module which uses the ngAnimate module as a dependency just like we did before
with `ngResource`. with `ngResource`.
@ -153,7 +157,7 @@ __`app/css/animations.css`__
</pre> </pre>
As you can see our `phone-listing` CSS class is combined together with the animation hooks that occur when items are As you can see our `phone-listing` CSS class is combined together with the animation hooks that occur when items are
inserted info and removed from the list: inserted into and removed from the list:
* The `ng-enter` class is applied to the element when a new phone is added to the list and rendered on the page. * The `ng-enter` class is applied to the element when a new phone is added to the list and rendered on the page.
* The `ng-move` class is applied when items are moved around in the list. * The `ng-move` class is applied when items are moved around in the list.
@ -289,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, 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? the profile phone image changes. But how can we change this around to add animations?
Lets think about it first, 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
basically when you click on a thumbnail image, you're changing the state of the profile image to reflect the newly
selected thumbnail image. selected thumbnail image.
The best way to specify state changes within HTML is to use classes. The best way to specify state changes within HTML is to use classes.
Much like before, how we used a CSS class to specify Much like before, how we used a CSS class to specify
@ -337,45 +340,58 @@ Although we could do that, let's take the opportunity to learn how to create Jav
__`app/js/animations.js`.__ __`app/js/animations.js`.__
<pre> <pre>
angular.module('phonecatAnimations', ['ngAnimate']) var phonecatAnimations = angular.module('phonecatAnimations', ['ngAnimate']);
.animation('.phone', function() { phonecatAnimations.animation('.phone', function() {
return {
addClass : function(element, className, done) {
if(className != 'active') {
return;
}
element.css({
position: 'absolute',
top: 500,
left: 0,
display: 'block'
});
jQuery(element).animate({
top: 0
}, done);
return function(cancel) { var animateUp = function(element, className, done) {
if(cancel) element.stop(); if(className != 'active') {
}; return;
}, }
removeClass : function(element, className, done) { element.css({
if(className != 'active') return; position: 'absolute',
element.css({ top: 500,
position: 'absolute', left: 0,
left: 0, display: 'block'
top: 0 });
});
jQuery(element).animate({
top: -500
}, done);
return function(cancel) { jQuery(element).animate({
if(cancel) element.stop(); top: 0
}; }, done);
return function(cancel) {
if(cancel) {
element.stop();
} }
}; };
}); }
var animateDown = function(element, className, done) {
if(className != 'active') {
return;
}
element.css({
position: 'absolute',
left: 0,
top: 0
});
jQuery(element).animate({
top: -500
}, done);
return function(cancel) {
if(cancel) {
element.stop();
}
};
}
return {
addClass: animateUp,
removeClass: animateDown
};
});
</pre> </pre>
Note that we're using {@link http://jquery.com/ jQuery} to implement the animation. jQuery Note that we're using {@link http://jquery.com/ jQuery} to implement the animation. jQuery
@ -383,10 +399,6 @@ isn't required to do JavaScript animations with AngularJS, but we're going to us
your own JavaScript animation library is beyond the scope of this tutorial. For more on your own JavaScript animation library is beyond the scope of this tutorial. For more on
`jQuery.animate`, see the {@link http://api.jquery.com/animate/ jQuery documentation}. `jQuery.animate`, see the {@link http://api.jquery.com/animate/ jQuery documentation}.
<div class="alert alert-error">
**Important:** Be sure to use jQuery version `1.10.x`. AngularJS does not yet support jQuery `2.x`.
</div>
The `addClass` and `removeClass` callback functions are called whenever an a class is added or removed The `addClass` and `removeClass` callback functions are called whenever an a class is added or removed
on the element that contains the class we registered, which is in this case `.phone`. When the `.active` on the element that contains the class we registered, which is in this case `.phone`. When the `.active`
class is added to the element (via the `ng-class` directive) the `addClass` JavaScript callback will class is added to the element (via the `ng-class` directive) the `addClass` JavaScript callback will

View file

@ -8,8 +8,6 @@ previous steps using the `git checkout` command.
For more details and examples of the Angular concepts we touched on in this tutorial, see the For more details and examples of the Angular concepts we touched on in this tutorial, see the
{@link guide/ Developer Guide}. {@link guide/ Developer Guide}.
For several more examples of code, see the {@link cookbook/ Cookbook}.
When you are ready to start developing a project using Angular, we recommend that you bootstrap When you are ready to start developing a project using Angular, we recommend that you bootstrap
your development with the {@link https://github.com/angular/angular-seed angular-seed} project. your development with the {@link https://github.com/angular/angular-seed angular-seed} project.

View file

@ -1,5 +1,7 @@
var ngdoc = require('../src/ngdoc.js'); var ngdoc = require('../src/ngdoc.js');
var DOM = require('../src/dom.js').DOM; var DOM = require('../src/dom.js').DOM;
var gruntUtil = require('../../lib/grunt/utils.js');
describe('ngdoc', function() { describe('ngdoc', function() {
var Doc = ngdoc.Doc; 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() { describe('TAG', function() {

View file

@ -3,7 +3,7 @@
*/ */
exports.appCache = appCache; exports.appCache = appCache;
var fs = require('q-fs'); var fs = require('q-io/fs');
var Q = require('qq'); var Q = require('qq');
function identity($) {return $;} function identity($) {return $;}

View file

@ -6,7 +6,8 @@ var makeUnique = {
'script.js': true, 'script.js': true,
'unit.js': true, 'unit.js': true,
'spec.js': true, 'spec.js': true,
'scenario.js': true 'scenario.js': true,
'protractorTest.js': true
} }
function ids(list) { function ids(list) {
@ -14,7 +15,7 @@ function ids(list) {
}; };
exports.Example = function(scenarios) { exports.Example = function(scenarios, protractorTests) {
this.module = ''; this.module = '';
this.deps = ['angular.js']; this.deps = ['angular.js'];
this.html = []; this.html = [];
@ -24,6 +25,8 @@ exports.Example = function(scenarios) {
this.unit = []; this.unit = [];
this.scenario = []; this.scenario = [];
this.scenarios = scenarios; this.scenarios = scenarios;
this.protractorTest = [];
this.protractorTests = protractorTests;
} }
exports.Example.prototype.setModule = function(module) { 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], var ext = name == 'scenario.js' ? 'scenario' : name.split('.')[1],
id = name; id = name;
if (name == 'protractorTest.js') {
ext = 'protractorTest';
}
if (makeUnique[name] && usedIds[id]) { if (makeUnique[name] && usedIds[id]) {
id = name + '-' + (seqCount++); id = name + '-' + (seqCount++);
} }
@ -56,6 +63,9 @@ exports.Example.prototype.addSource = function(name, content) {
if (ext == 'scenario') { if (ext == 'scenario') {
this.scenarios.push(content); this.scenarios.push(content);
} }
if (ext == 'protractorTest') {
this.protractorTests.push(content);
}
}; };
exports.Example.prototype.enableAnimations = function() { 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-json="' + ids(this.json) + '"');
out.push(' source-edit-unit="' + ids(this.unit) + '"'); out.push(' source-edit-unit="' + ids(this.unit) + '"');
out.push(' source-edit-scenario="' + ids(this.scenario) + '"'); out.push(' source-edit-scenario="' + ids(this.scenario) + '"');
out.push(' source-edit-protractor="' + ids(this.protractorTest) + '"');
out.push('></div>\n'); out.push('></div>\n');
return out.join(''); return out.join('');
}; };
@ -107,6 +118,7 @@ exports.Example.prototype.toHtmlTabs = function() {
htmlTabs(this.json); htmlTabs(this.json);
htmlTabs(this.unit); htmlTabs(this.unit);
htmlTabs(this.scenario); htmlTabs(this.scenario);
htmlTabs(this.protractorTest);
out.push('</div>'); out.push('</div>');
return out.join(''); return out.join('');
@ -119,7 +131,8 @@ exports.Example.prototype.toHtmlTabs = function() {
if (name === 'index.html') { if (name === 'index.html') {
wrap = ' ng-html-wrap="' + self.module + ' ' + self.deps.join(' ') + '"'; 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( out.push(
'<div class="tab-pane" title="' + name + '">\n' + '<div class="tab-pane" title="' + name + '">\n' +

View file

@ -17,6 +17,8 @@ writer.makeDir('build/docs/', true).then(function() {
return writer.makeDir('build/docs/components/bootstrap'); return writer.makeDir('build/docs/components/bootstrap');
}).then(function() { }).then(function() {
return writer.makeDir('build/docs/components/font-awesome'); return writer.makeDir('build/docs/components/font-awesome');
}).then(function() {
return writer.makeDir('build/docs/e2etests');
}).then(function() { }).then(function() {
console.log('Generating AngularJS Reference Documentation...'); console.log('Generating AngularJS Reference Documentation...');
return reader.collect(); return reader.collect();
@ -53,6 +55,10 @@ writer.makeDir('build/docs/', true).then(function() {
var id = doc.id.replace('angular.Module', 'angular.IModule'); var id = doc.id.replace('angular.Module', 'angular.IModule');
fileFutures.push(writer.output('partials/' + doc.section + '/' + id + '.html', doc.html())); 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); ngdoc.checkBrokenLinks(docs);
@ -74,10 +80,10 @@ function writeTheRest(writesFuture) {
var versions = ngdoc.ngVersions(); var versions = ngdoc.ngVersions();
var currentVersion = ngdoc.ngCurrentVersion(); var currentVersion = ngdoc.ngCurrentVersion();
writesFuture.push(writer.symlink('../../docs/content/notes', 'build/docs/notes', 'dir')); writesFuture.push(writer.symlink('../../docs/content/notes', 'build/docs/notes', 'directory'));
writesFuture.push(writer.symlinkTemplate('css', 'dir')); writesFuture.push(writer.symlinkTemplate('css', 'directory'));
writesFuture.push(writer.symlink('../../docs/img', 'build/docs/img', 'dir')); writesFuture.push(writer.symlink('../../docs/img', 'build/docs/img', 'directory'));
writesFuture.push(writer.symlinkTemplate('js', 'dir')); writesFuture.push(writer.symlinkTemplate('js', 'directory'));
var manifest = 'manifest="/build/docs/appcache.manifest"'; var manifest = 'manifest="/build/docs/appcache.manifest"';

View file

@ -35,6 +35,7 @@ var lookupMinerrMsg = function (doc) {
exports.trim = trim; exports.trim = trim;
exports.metadata = metadata; exports.metadata = metadata;
exports.scenarios = scenarios; exports.scenarios = scenarios;
exports.writeProtractorTest = writeProtractorTest;
exports.merge = merge; exports.merge = merge;
exports.checkBrokenLinks = checkBrokenLinks; exports.checkBrokenLinks = checkBrokenLinks;
exports.Doc = Doc; exports.Doc = Doc;
@ -50,7 +51,7 @@ exports.ngVersions = function() {
}); });
//match the future version of AngularJS that is set in the package.json file //match the future version of AngularJS that is set in the package.json file
return expandVersions(sortVersionsNatrually(versions), exports.ngCurrentVersion().full); return expandVersions(sortVersionsNaturally(versions), exports.ngCurrentVersion().full);
function expandVersions(versions, latestVersion) { function expandVersions(versions, latestVersion) {
var RC_VERSION = /rc\d/; var RC_VERSION = /rc\d/;
@ -86,7 +87,7 @@ exports.ngVersions = function() {
return expanded; return expanded;
}; };
function sortVersionsNatrually(versions) { function sortVersionsNaturally(versions) {
var versionMap = {}, var versionMap = {},
NON_RC_RELEASE_NUMBER = 999; NON_RC_RELEASE_NUMBER = 999;
for(var i = versions.length - 1; i >= 0; i--) { for(var i = versions.length - 1; i >= 0; i--) {
@ -155,6 +156,7 @@ function Doc(text, file, line) {
this.line = line; this.line = line;
} }
this.scenarios = this.scenarios || []; this.scenarios = this.scenarios || [];
this.protractorTests = this.protractorTests || [];
this.requires = this.requires || []; this.requires = this.requires || [];
this.param = this.param || []; this.param = this.param || [];
this.properties = this.properties || []; this.properties = this.properties || [];
@ -292,7 +294,7 @@ Doc.prototype = {
replace(/<example(?:\s+module="([^"]*)")?(?:\s+deps="([^"]*)")?(\s+animations="true")?>([\s\S]*?)<\/example>/gmi, replace(/<example(?:\s+module="([^"]*)")?(?:\s+deps="([^"]*)")?(\s+animations="true")?>([\s\S]*?)<\/example>/gmi,
function(_, module, deps, animations, content) { function(_, module, deps, animations, content) {
var example = new Example(self.scenarios); var example = new Example(self.scenarios, self.protractorTests);
if(animations) { if(animations) {
example.enableAnimations(); example.enableAnimations();
example.addDeps('angular-animate.js'); example.addDeps('angular-animate.js');
@ -329,7 +331,7 @@ Doc.prototype = {
}). }).
replace(/^<doc:example(\s+[^>]*)?>([\s\S]*)<\/doc:example>/mi, function(_, attrs, content) { replace(/^<doc:example(\s+[^>]*)?>([\s\S]*)<\/doc:example>/mi, function(_, attrs, content) {
var html, script, scenario, 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]); example.setModule((attrs||'module=""').match(/^\s*module=["'](.*)["']\s*$/)[1]);
content. content.
@ -347,6 +349,8 @@ Doc.prototype = {
}). }).
replace(/(<doc:scenario>)([\s\S]*)(<\/doc:scenario>)/mi, function(_, before, content){ replace(/(<doc:scenario>)([\s\S]*)(<\/doc:scenario>)/mi, function(_, before, content){
example.addSource('scenario.js', 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()); return placeholder(example.toHtml());
@ -548,7 +552,7 @@ Doc.prototype = {
minerrMsg; minerrMsg;
var gitTagFromFullVersion = function(version) { var gitTagFromFullVersion = function(version) {
var match = version.match(/-(\w{7})/); var match = version.match(/sha\.(\w{7})/);
if (match) { if (match) {
// git sha // 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){ function metadata(docs){
@ -1381,6 +1401,14 @@ function explainModuleInstallation(moduleName){
modulePackage = 'angular-' + moduleName, modulePackage = 'angular-' + moduleName,
modulePackageFile = modulePackage + '.js'; modulePackageFile = modulePackage + '.js';
// Deal with inconsistent ngMock naming - doing it verbosely and explicitly here
// rather than cleverly interweaving it in the previous lines to make it obvious
// what is going on
if ( moduleName == 'mock' ) {
modulePackage = 'angular-mocks';
modulePackageFile = modulePackage + '.js';
}
return '<h1>Installation</h1>' + return '<h1>Installation</h1>' +
'<p>First include <code>' + modulePackageFile +'</code> in your HTML:</p><pre><code>' + '<p>First include <code>' + modulePackageFile +'</code> in your HTML:</p><pre><code>' +
' &lt;script src=&quot;angular.js&quot;&gt;\n' + ' &lt;script src=&quot;angular.js&quot;&gt;\n' +

View file

@ -7,7 +7,7 @@ exports.collect = collect;
var ngdoc = require('./ngdoc.js'), var ngdoc = require('./ngdoc.js'),
Q = require('qq'), Q = require('qq'),
qfs = require('q-fs'), qfs = require('q-io/fs'),
PATH = require('path'); PATH = require('path');
var NEW_LINE = /\n\r?/; var NEW_LINE = /\n\r?/;

View file

@ -16,4 +16,4 @@ RewriteCond %{HTTP_HOST} ^docs-next\.angularjs\.org$
RewriteRule appcache.manifest http://code.angularjs.org/next/docs/appcache.manifest [R=301] RewriteRule appcache.manifest http://code.angularjs.org/next/docs/appcache.manifest [R=301]
## HTML5 URL Support ## ## HTML5 URL Support ##
RewriteRule ^(guide|api|cookbook|misc|tutorial)(/.*)?$ index.html RewriteRule ^(guide|api|misc|tutorial)(/.*)?$ index.html

View file

@ -144,6 +144,32 @@
.content h4, .content h4,
.content h5 { .content h5 {
margin-top: 1em; 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, ul.parameters > li > p,
@ -220,6 +246,10 @@ ul.events > li > h3 {
text-decoration: none; text-decoration: none;
} }
.tutorial-nav li {
margin-right: 5px;
}
.clear { .clear {
clear: both; clear: both;
} }
@ -522,6 +552,10 @@ pre ol li {
margin-bottom:30px; margin-bottom:30px;
} }
.definition-table td {
vertical-align: top;
}
.component-heading { .component-heading {
text-transform:capitalize; text-transform:capitalize;
} }

View file

@ -26,7 +26,7 @@
} }
var indexFile = (location.pathname.match(/\/(index[^\.]*\.html)/) || ['', ''])[1], var indexFile = (location.pathname.match(/\/(index[^\.]*\.html)/) || ['', ''])[1],
rUrl = /(#!\/|api|guide|misc|tutorial|cookbook|error|index[^\.]*\.html).*$/, rUrl = /(#!\/|api|guide|misc|tutorial|error|index[^\.]*\.html).*$/,
baseUrl = location.href.replace(rUrl, indexFile), baseUrl = location.href.replace(rUrl, indexFile),
jQuery = /index-jq[^\.]*\.html$/.test(baseUrl), jQuery = /index-jq[^\.]*\.html$/.test(baseUrl),
debug = /index[^\.]*-debug\.html$/.test(baseUrl), debug = /index[^\.]*-debug\.html$/.test(baseUrl),
@ -334,11 +334,6 @@
<div id="loading" ng-show="loading">Loading...</div> <div id="loading" ng-show="loading">Loading...</div>
<div ng-hide="loading" ng-include src="currentPage.partialUrl" onload="afterPartialLoaded()" autoscroll class="content slide-reveal"></div> <div ng-hide="loading" ng-include src="currentPage.partialUrl" onload="afterPartialLoaded()" autoscroll class="content slide-reveal"></div>
<div id="disqus" class="disqus">
<h2>Discussion</h2>
<div id="disqus_thread" class="content-panel-content"></div>
</div>
</div> </div>
</div> </div>
</div> </div>
@ -365,7 +360,7 @@
<footer class="footer"> <footer class="footer">
<div class="container"> <div class="container">
<p class="pull-right"><a href="#">Back to top</a></p> <p class="pull-right"><a back-to-top href="#">Back to top</a></p>
<p> <p>
Super-powered by Google ©2010-2012 Super-powered by Google ©2010-2012

View file

@ -5,11 +5,19 @@ var docsApp = {
filter: {} 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_versions = NG_VERSIONS;
$scope.docs_version = NG_VERSIONS[0]; $scope.docs_version = NG_VERSIONS[0];
$scope.jumpToDocsVersion = function(version) { $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;
}; };
}]; }];
@ -103,9 +111,6 @@ docsApp.serviceFactory.docsSearch = ['$rootScope','lunrSearch', 'NG_PAGES',
angular.forEach(index.search(q), function(result) { angular.forEach(index.search(q), function(result) {
var item = NG_PAGES[result.ref]; var item = NG_PAGES[result.ref];
var section = item.section; var section = item.section;
if(section == 'cookbook') {
section = 'tutorial';
}
results[section] = results[section] || []; results[section] = results[section] || [];
if(results[section].length < 15) { if(results[section].length < 15) {
results[section].push(item); results[section].push(item);
@ -137,11 +142,19 @@ docsApp.directive.docsSearchInput = ['$document',function($document) {
var ESCAPE_KEY_KEYCODE = 27, var ESCAPE_KEY_KEYCODE = 27,
FORWARD_SLASH_KEYCODE = 191; FORWARD_SLASH_KEYCODE = 191;
angular.element($document[0].body).bind('keydown', function(event) { angular.element($document[0].body).bind('keydown', function(event) {
var input = element[0]; if(event.keyCode == FORWARD_SLASH_KEYCODE && document.activeElement) {
if(event.keyCode == FORWARD_SLASH_KEYCODE && document.activeElement != input) { var activeElement = document.activeElement;
event.stopPropagation(); var activeTagName = activeElement.nodeName.toLowerCase();
event.preventDefault(); var hasInputFocus = activeTagName == 'input' || activeTagName == 'select' ||
input.focus(); activeTagName == 'option' || activeTagName == 'textarea' ||
activeElement.hasAttribute('contenteditable');
if(!hasInputFocus) {
event.stopPropagation();
event.preventDefault();
var input = element[0];
input.focus();
}
} }
}); });
@ -273,10 +286,10 @@ docsApp.directive.docTutorialNav = function(templateMerge) {
element.addClass('btn-group'); element.addClass('btn-group');
element.addClass('tutorial-nav'); element.addClass('tutorial-nav');
element.append(templateMerge( element.append(templateMerge(
'<li class="btn btn-primary"><a href="tutorial/{{prev}}"><i class="icon-step-backward"></i> Previous</a></li>\n' + '<a href="tutorial/{{prev}}"><li class="btn btn-primary"><i class="icon-step-backward"></i> Previous</li></a>\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' + '<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' +
'<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' + '<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' +
'<li class="btn btn-primary"><a href="tutorial/{{next}}">Next <i class="icon-step-forward"></i></a></li>', props)); '<a href="tutorial/{{next}}"><li class="btn btn-primary">Next <i class="icon-step-forward"></i></li></a>', props));
} }
}; };
}; };
@ -372,6 +385,21 @@ docsApp.directive.errorDisplay = ['$location', 'errorLinkFilter', function ($loc
}]; }];
/**
* backToTop Directive
* @param {Function} $anchorScroll
*
* @description Ensure that the browser scrolls when the anchor is clicked
*/
docsApp.directive.backToTop = ['$anchorScroll', function($anchorScroll) {
return function link(scope, element) {
element.on('click', function(event) {
scope.$apply($anchorScroll);
});
};
}];
docsApp.serviceFactory.angularUrls = function($document) { docsApp.serviceFactory.angularUrls = function($document) {
var urls = {}; var urls = {};
@ -599,7 +627,6 @@ docsApp.serviceFactory.sections = ['NG_PAGES', function sections(NG_PAGES) {
api: [], api: [],
tutorial: [], tutorial: [],
misc: [], misc: [],
cookbook: [],
error: [], error: [],
getPage: function(sectionId, partialId) { getPage: function(sectionId, partialId) {
var pages = sections[sectionId]; var pages = sections[sectionId];
@ -630,7 +657,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) { $scope.fold = function(url) {
if(url) { if(url) {
$scope.docs_fold = '/notes/' + url; $scope.docs_fold = '/notes/' + url;
@ -644,7 +671,7 @@ docsApp.controller.DocsController = function($scope, $location, $window, $cookie
} }
}; };
var OFFLINE_COOKIE_NAME = 'ng-offline', var OFFLINE_COOKIE_NAME = 'ng-offline',
DOCS_PATH = /^\/(api)|(guide)|(cookbook)|(misc)|(tutorial)|(error)/, DOCS_PATH = /^\/(api)|(guide)|(misc)|(tutorial)|(error)/,
INDEX_PATH = /^(\/|\/index[^\.]*.html)$/, INDEX_PATH = /^(\/|\/index[^\.]*.html)$/,
GLOBALS = /^angular\.([^\.]+)$/, GLOBALS = /^angular\.([^\.]+)$/,
ERROR = /^([a-zA-Z0-9_$]+:)?([a-zA-Z0-9_$]+)$/, ERROR = /^([a-zA-Z0-9_$]+:)?([a-zA-Z0-9_$]+)$/,
@ -680,7 +707,6 @@ docsApp.controller.DocsController = function($scope, $location, $window, $cookie
var currentPageId = $location.path(); var currentPageId = $location.path();
$scope.partialTitle = $scope.currentPage.shortName; $scope.partialTitle = $scope.currentPage.shortName;
$window._gaq.push(['_trackPageview', currentPageId]); $window._gaq.push(['_trackPageview', currentPageId]);
loadDisqus(currentPageId);
}; };
/** stores a cookie that is used by apache to decide which manifest ot send */ /** stores a cookie that is used by apache to decide which manifest ot send */
@ -707,7 +733,6 @@ docsApp.controller.DocsController = function($scope, $location, $window, $cookie
guide: 'Developer Guide', guide: 'Developer Guide',
misc: 'Miscellaneous', misc: 'Miscellaneous',
tutorial: 'Tutorial', tutorial: 'Tutorial',
cookbook: 'Examples',
error: 'Error Reference' error: 'Error Reference'
}; };
@ -722,9 +747,9 @@ docsApp.controller.DocsController = function($scope, $location, $window, $cookie
sectionName = SECTION_NAME[sectionId] || sectionId, sectionName = SECTION_NAME[sectionId] || sectionId,
page = sections.getPage(sectionId, partialId); 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!'; $scope.partialTitle = 'Error: Page Not Found!';
} }
@ -892,29 +917,6 @@ docsApp.controller.DocsController = function($scope, $location, $window, $cookie
return namespace; return namespace;
} }
} }
function loadDisqus(currentPageId) {
// http://docs.disqus.com/help/2/
window.disqus_shortname = 'angularjs-next';
window.disqus_identifier = currentPageId;
window.disqus_url = 'http://docs.angularjs.org' + currentPageId;
if ($location.host() == 'localhost') {
return; // don't display disqus on localhost, comment this out if needed
//window.disqus_developer = 1;
}
// http://docs.disqus.com/developers/universal/
(function() {
var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
dsq.src = 'http://angularjs.disqus.com/embed.js';
(document.getElementsByTagName('head')[0] ||
document.getElementsByTagName('body')[0]).appendChild(dsq);
})();
angular.element(document.getElementById('disqus_thread')).html('');
}
}; };

View file

@ -3,7 +3,7 @@
* for testability * for testability
*/ */
var pathUtils = require('path'); var pathUtils = require('path');
var qfs = require('q-fs'); var qfs = require('q-io/fs');
var Q = require('qq'); var Q = require('qq');
var OUTPUT_DIR = pathUtils.join('build','docs'); var OUTPUT_DIR = pathUtils.join('build','docs');
var TEMPLATES_DIR = pathUtils.join('docs','src','templates'); 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 // qfs will normalize the path arguments for us here
return qfs.exists(to).then(function(exists) { return qfs.exists(to).then(function(exists) {
if (!exists) { if (!exists) {
return qfs.symbolicLink(to, from, type); return qfs.symbolicLink(to, from, type || 'file');
} }
}); });
} }

View file

@ -1,9 +1,12 @@
#!/bin/bash #!/bin/bash
echo "#################################"
echo "#### Jenkins Build ############"
echo "#################################"
# Enable tracing and exit on first failure # Enable tracing and exit on first failure
set -xe set -xe
# Define reasonable set of browsers in case we are running manually from commandline # Define reasonable set of browsers in case we are running manually from commandline
if [[ -z "$BROWSERS" ]] if [[ -z "$BROWSERS" ]]
then then
@ -25,13 +28,15 @@ rm -f angular.js.size
npm install --color false npm install --color false
grunt ci-checks package --no-color grunt ci-checks package --no-color
# DOCS generator unit tests #
grunt test:docgen --no-color
# UNIT TESTS # # UNIT TESTS #
grunt test:unit --browsers $BROWSERS --reporters=dots,junit --no-colors --no-color grunt test:unit --browsers $BROWSERS --reporters=dots,junit --no-colors --no-color
# END TO END TESTS # # END TO END TESTS #
grunt test:e2e --browsers $BROWSERS_E2E --reporters=dots,junit --no-colors --no-color grunt test:e2e --browsers $BROWSERS_E2E --reporters=dots,junit --no-colors --no-color
grunt test:protractor
# Promises/A+ TESTS # # Promises/A+ TESTS #
grunt test:promises-aplus --no-color grunt test:promises-aplus --no-color

View file

@ -10,12 +10,12 @@ module.exports = function(config) {
'build/angular.js', 'build/angular.js',
'build/angular-cookies.js', 'build/angular-cookies.js',
'build/angular-mocks.js',
'build/angular-resource.js', 'build/angular-resource.js',
'build/angular-touch.js', 'build/angular-touch.js',
'build/angular-sanitize.js', 'build/angular-sanitize.js',
'build/angular-route.js', 'build/angular-route.js',
'build/angular-animate.js', 'build/angular-animate.js',
'build/angular-mocks.js',
'build/docs/components/lunr.js', 'build/docs/components/lunr.js',
'build/docs/components/google-code-prettify.js', 'build/docs/components/google-code-prettify.js',

View file

@ -1,25 +0,0 @@
var sharedConfig = require('./karma-shared.conf');
module.exports = function(config) {
sharedConfig(config, {testName: 'AngularJS: e2e', logFile: 'karma-e2e.log'});
config.set({
frameworks: [],
files: [
'build/angular-scenario.js',
'node_modules/karma-ng-scenario/lib/adapter.js',
'build/docs/docs-scenario.js'
],
proxies: {
// angular.js, angular-resource.js, etc
'/angular': 'http://localhost:8000/build/angular',
'/': 'http://localhost:8000/build/docs/'
},
junitReporter: {
outputFile: 'test_out/e2e.xml',
suite: 'E2E'
}
});
};

View file

@ -6,13 +6,25 @@ module.exports = function(config, specificOptions) {
logColors: true, logColors: true,
browsers: ['Chrome'], browsers: ['Chrome'],
browserDisconnectTimeout: 10000, browserDisconnectTimeout: 10000,
browserDisconnectTolerance: 2,
browserNoActivityTimeout: 20000,
// config for Travis CI // SauceLabs config for local development.
sauceLabs: { sauceLabs: {
testName: specificOptions.testName || 'AngularJS', testName: specificOptions.testName || 'AngularJS',
startConnect: false, startConnect: true,
tunnelIdentifier: process.env.TRAVIS_JOB_NUMBER options: {
'selenium-version': '2.37.0'
}
},
// BrowserStack config for local development.
browserStack: {
project: 'AngularJS',
name: specificOptions.testName,
startTunnel: true,
timeout: 600 // 10min
}, },
// For more browsers on Sauce Labs see: // For more browsers on Sauce Labs see:
@ -24,13 +36,14 @@ module.exports = function(config, specificOptions) {
}, },
'SL_Firefox': { 'SL_Firefox': {
base: 'SauceLabs', base: 'SauceLabs',
browserName: 'firefox' browserName: 'firefox',
version: '26'
}, },
'SL_Safari': { 'SL_Safari': {
base: 'SauceLabs', base: 'SauceLabs',
browserName: 'safari', browserName: 'safari',
platform: 'Mac 10.8', platform: 'OS X 10.9',
version: '6' version: '7'
}, },
'SL_IE_8': { 'SL_IE_8': {
base: 'SauceLabs', base: 'SauceLabs',
@ -49,12 +62,77 @@ module.exports = function(config, specificOptions) {
browserName: 'internet explorer', browserName: 'internet explorer',
platform: 'Windows 2012', platform: 'Windows 2012',
version: '10' version: '10'
},
'SL_IE_11': {
base: 'SauceLabs',
browserName: 'internet explorer',
platform: 'Windows 8.1',
version: '11'
},
'BS_Chrome': {
base: 'BrowserStack',
browser: 'chrome',
os: 'OS X',
os_version: 'Mountain Lion'
},
'BS_Safari': {
base: 'BrowserStack',
browser: 'safari',
os: 'OS X',
os_version: 'Mountain Lion'
},
'BS_Firefox': {
base: 'BrowserStack',
browser: 'firefox',
os: 'Windows',
os_version: '8'
},
'BS_IE_8': {
base: 'BrowserStack',
browser: 'ie',
browser_version: '8.0',
os: 'Windows',
os_version: '7'
},
'BS_IE_9': {
base: 'BrowserStack',
browser: 'ie',
browser_version: '9.0',
os: 'Windows',
os_version: '7'
},
'BS_IE_10': {
base: 'BrowserStack',
browser: 'ie',
browser_version: '10.0',
os: 'Windows',
os_version: '8'
},
'BS_IE_11': {
base: 'BrowserStack',
browser: 'ie',
browser_version: '11.0',
os: 'Windows',
os_version: '8.1'
} }
} }
}); });
if (process.env.TRAVIS) { if (process.env.TRAVIS) {
var buildLabel = 'TRAVIS #' + process.env.TRAVIS_BUILD_NUMBER + ' (' + process.env.TRAVIS_BUILD_ID + ')';
config.logLevel = config.LOG_DEBUG;
config.transports = ['websocket', 'xhr-polling'];
config.browserStack.build = buildLabel;
config.browserStack.startTunnel = false;
config.sauceLabs.build = buildLabel;
config.sauceLabs.startConnect = false;
config.sauceLabs.tunnelIdentifier = process.env.TRAVIS_JOB_NUMBER;
// TODO(vojta): remove once SauceLabs supports websockets. // TODO(vojta): remove once SauceLabs supports websockets.
// This speeds up the capturing a bit, as browsers don't even try to use websocket. // This speeds up the capturing a bit, as browsers don't even try to use websocket.
config.transports = ['xhr-polling']; config.transports = ['xhr-polling'];
@ -62,8 +140,47 @@ module.exports = function(config, specificOptions) {
// Debug logging into a file, that we print out at the end of the build. // Debug logging into a file, that we print out at the end of the build.
config.loggers.push({ config.loggers.push({
type: 'file', type: 'file',
filename: process.env.LOGS_DIR + '/' + (specificOptions.logFile || 'karma.log'), filename: process.env.LOGS_DIR + '/' + (specificOptions.logFile || 'karma.log')
level: config.LOG_DEBUG
}); });
} }
// Terrible hack to workaround inflexibility of log4js:
// - ignore web-server's 404 warnings,
// - ignore DEBUG logs (on Travis), we log them into a file instead.
var IGNORED_404 = [
'/favicon.ico',
'/%7B%7BtestUrl%7D%7D',
'/someSanitizedUrl',
'/{{testUrl}}'
];
var log4js = require('./node_modules/karma/node_modules/log4js');
var layouts = require('./node_modules/karma/node_modules/log4js/lib/layouts');
var originalConfigure = log4js.configure;
log4js.configure = function(log4jsConfig) {
var consoleAppender = log4jsConfig.appenders.shift();
var originalResult = originalConfigure.call(log4js, log4jsConfig);
var layout = layouts.layout(consoleAppender.layout.type, consoleAppender.layout);
log4js.addAppender(function(log) {
var msg = log.data[0];
// ignore web-server's 404s
if (log.categoryName === 'web-server' && log.level.levelStr === config.LOG_WARN &&
IGNORED_404.some(function(ignoredLog) {return msg.indexOf(ignoredLog) !== -1})) {
return;
}
// on Travis, ignore DEBUG statements
if (process.env.TRAVIS && log.level.levelStr === config.LOG_DEBUG) {
return;
}
console.log(layout(log));
});
return originalResult;
};
}; };

View file

@ -0,0 +1,46 @@
var fs = require('fs');
var http = require('http');
var BrowserStackTunnel = require('browserstacktunnel-wrapper');
var HOSTNAME = 'localhost';
var PORTS = require('../grunt/utils').availablePorts;
var ACCESS_KEY = process.env.BROWSER_STACK_ACCESS_KEY;
var READY_FILE = process.env.SAUCE_CONNECT_READY_FILE;
// We need to start fake servers, otherwise the tunnel does not start.
var fakeServers = [];
var hosts = [];
PORTS.forEach(function(port) {
fakeServers.push(http.createServer(function() {}).listen(port));
hosts.push({
name: HOSTNAME,
port: port,
sslFlag: 0
});
});
var tunnel = new BrowserStackTunnel({
key: ACCESS_KEY,
hosts: hosts
});
console.log('Starting tunnel on ports', PORTS.join(', '));
tunnel.start(function(error) {
if (error) {
console.error('Can not establish the tunnel', error);
} else {
console.log('Tunnel established.');
fakeServers.forEach(function(server) {
server.close();
});
if (READY_FILE) {
fs.writeFile(READY_FILE, '');
}
}
});
tunnel.on('error', function(error) {
console.error(error);
});

View file

@ -0,0 +1 @@
node ./lib/browser-stack/start-tunnel.js &

View file

@ -61,6 +61,14 @@ module.exports = function(grunt) {
util.startKarma.call(util, this.data, false, this.async()); 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 () { grunt.registerTask('collect-errors', 'Combine stripped error files', function () {
util.collectErrors(); util.collectErrors();
}); });

View file

@ -2,9 +2,26 @@ var fs = require('fs');
var shell = require('shelljs'); var shell = require('shelljs');
var grunt = require('grunt'); var grunt = require('grunt');
var spawn = require('child_process').spawn; var spawn = require('child_process').spawn;
var semver = require('semver');
var version; var version;
var CSP_CSS_HEADER = '/* Include this file in your html if you are using the CSP mode. */\n\n'; var CSP_CSS_HEADER = '/* Include this file in your html if you are using the CSP mode. */\n\n';
var PORT_MIN = 8000;
var PORT_MAX = 9999;
var TRAVIS_BUILD_NUMBER = parseInt(process.env.TRAVIS_BUILD_NUMBER, 10);
var getRandomPorts = function() {
if (!process.env.TRAVIS) {
return [9876, 9877];
}
// Generate two numbers between PORT_MIN and PORT_MAX, based on TRAVIS_BUILD_NUMBER.
return [
PORT_MIN + (TRAVIS_BUILD_NUMBER % (PORT_MAX - PORT_MIN)),
PORT_MIN + ((TRAVIS_BUILD_NUMBER + 100) % (PORT_MAX - PORT_MIN))
];
};
module.exports = { module.exports = {
init: function() { init: function() {
@ -16,29 +33,85 @@ module.exports = {
getVersion: function(){ getVersion: function(){
if (version) return version; if (version) return version;
var package = JSON.parse(fs.readFileSync('package.json', 'UTF-8')); var package = JSON.parse(fs.readFileSync('package.json', 'UTF-8'));
var match = package.version.match(/^([^\-]*)(?:\-(.+))?$/); try {
var semver = match[1].split('.');
var hash = shell.exec('git rev-parse --short HEAD', {silent: true}).output.replace('\n', '');
var fullVersion = match[1]; var gitTag = getTagOfCurrentCommit();
var semVerVersion, codeName, fullVersion;
if (gitTag) {
// tagged release
fullVersion = semVerVersion = semver.valid(gitTag);
codeName = getTaggedReleaseCodeName(gitTag);
} else {
// snapshot release
semVerVersion = getSnapshotVersion();
fullVersion = semVerVersion + '-' + getSnapshotSuffix();
codeName = 'snapshot'
}
if (match[2]) { var versionParts = semVerVersion.match(/(\d+)\.(\d+)\.(\d+)/);
fullVersion += '-';
fullVersion += (match[2] == 'snapshot') ? hash : match[2]; version = {
full: fullVersion,
major: versionParts[1],
minor: versionParts[2],
dot: versionParts[3],
codename: codeName,
cdn: package.cdnVersion
};
return version;
} catch (e) {
grunt.fail.warn(e);
} }
version = { function getTagOfCurrentCommit() {
full: fullVersion, var gitTagResult = shell.exec('git describe --exact-match', {silent:true});
major: semver[0], var gitTagOutput = gitTagResult.output.trim();
minor: semver[1], var branchVersionPattern = new RegExp(package.branchVersion.replace('.', '\\.').replace('*', '\\d+'));
dot: semver[2].replace(/rc\d+/, ''), if (gitTagResult.code === 0 && gitTagOutput.match(branchVersionPattern)) {
codename: package.codename, return gitTagOutput;
cdn: package.cdnVersion } else {
}; return null;
}
}
return version; function getTaggedReleaseCodeName(tagName) {
var tagMessage = shell.exec('git cat-file -p '+ tagName +' | grep "codename"', {silent:true}).output;
var codeName = tagMessage && tagMessage.match(/codename\((.*)\)/)[1];
if (!codeName) {
throw new Error("Could not extract release code name. The message of tag "+tagName+
" must match '*codename(some release name)*'");
}
return codeName;
}
function getSnapshotVersion() {
var oldTags = shell.exec('git tag -l v'+package.branchVersion, {silent:true}).output.trim().split('\n');
// ignore non semver versions.
oldTags = oldTags.filter(function(version) {
return version && semver.valid(version);
});
if (oldTags.length) {
oldTags.sort(semver.compare);
semVerVersion = oldTags[oldTags.length-1];
if (semVerVersion.indexOf('-') !== -1) {
semVerVersion = semver.inc(semVerVersion, 'prerelease');
} else {
semVerVersion = semver.inc(semVerVersion, 'patch');
}
} else {
semVerVersion = semver.valid(package.branchVersion.replace(/\*/g, '0'));
}
return semVerVersion;
}
function getSnapshotSuffix() {
var jenkinsBuild = process.env.TRAVIS_BUILD_NUMBER || process.env.BUILD_NUMBER || 'local';
var hash = shell.exec('git rev-parse --short HEAD', {silent: true}).output.replace('\n', '');
return 'build.'+jenkinsBuild+'+sha.'+hash;
}
}, },
@ -63,6 +136,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){ wrap: function(src, name){
src.unshift('src/' + name + '.prefix'); src.unshift('src/' + name + '.prefix');
src.push('src/' + name + '.suffix'); src.push('src/' + name + '.suffix');
@ -295,5 +400,7 @@ module.exports = {
}, },
// see http://saucelabs.com/docs/connect#localhost // see http://saucelabs.com/docs/connect#localhost
sauceLabsAvailablePorts: [9000, 9001, 9080, 9090, 9876] sauceLabsAvailablePorts: [9000, 9001, 9080, 9090, 9876],
// pseudo-random port numbers for BrowserStack
availablePorts: getRandomPorts()
}; };

View file

@ -36,8 +36,8 @@ ARGS=""
if [ ! -z "$TRAVIS_JOB_NUMBER" ]; then if [ ! -z "$TRAVIS_JOB_NUMBER" ]; then
ARGS="$ARGS --tunnel-identifier $TRAVIS_JOB_NUMBER" ARGS="$ARGS --tunnel-identifier $TRAVIS_JOB_NUMBER"
fi fi
if [ ! -z "$SAUCE_CONNECT_READY_FILE" ]; then if [ ! -z "$BROWSER_PROVIDER_READY_FILE" ]; then
ARGS="$ARGS --readyfile $SAUCE_CONNECT_READY_FILE" ARGS="$ARGS --readyfile $BROWSER_PROVIDER_READY_FILE"
fi fi

View file

@ -1,43 +1,49 @@
{ {
"name": "angularjs", "name": "angularjs",
"version": "1.2.2", "branchVersion": "1.2.*",
"cdnVersion": "1.2.1", "cdnVersion": "1.2.11",
"codename": "consciousness-inertia",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "https://github.com/angular/angular.js.git" "url": "https://github.com/angular/angular.js.git"
}, },
"devDependencies": { "devDependencies": {
"grunt": "~0.4.1", "grunt": "~0.4.2",
"bower": "~1.2.2", "grunt-bump": "~0.0.13",
"grunt-contrib-clean": "~0.5.0", "grunt-contrib-clean": "~0.5.0",
"grunt-contrib-compress": "~0.5.2",
"grunt-contrib-connect": "~0.5.0", "grunt-contrib-connect": "~0.5.0",
"grunt-contrib-compress": "~0.5.2",
"grunt-contrib-copy": "~0.4.1", "grunt-contrib-copy": "~0.4.1",
"grunt-contrib-jshint": "~0.7.2",
"grunt-ddescribe-iit": "~0.0.1",
"grunt-jasmine-node": "git://github.com/vojtajina/grunt-jasmine-node.git#fix-grunt-exit-code",
"grunt-jscs-checker": "~0.3.2",
"grunt-merge-conflict": "~0.0.1",
"grunt-parallel": "~0.3.1",
"grunt-shell": "~0.4.0",
"load-grunt-tasks": "~0.3.0",
"bower": "~1.2.2",
"jasmine-node": "~1.11.0", "jasmine-node": "~1.11.0",
"q": "~0.9.2", "q": "~0.9.2",
"q-fs": "~0.1.36", "q-io": "~1.10.6",
"qq": "~0.3.5", "qq": "~0.3.5",
"shelljs": "~0.2.6", "shelljs": "~0.2.6",
"karma": "~0.11", "karma": "0.11.12",
"karma-jasmine": "~0.1.0", "karma-jasmine": "0.1.5",
"karma-chrome-launcher": "~0.1.0", "karma-chrome-launcher": "0.1.2",
"karma-firefox-launcher": "~0.1.0", "karma-firefox-launcher": "0.1.3",
"karma-ng-scenario": "~0.1.0", "karma-ng-scenario": "0.1.0",
"karma-junit-reporter": "git://github.com/karma-runner/karma-junit-reporter#karma-0.11", "karma-junit-reporter": "0.2.1",
"karma-sauce-launcher": "~0.1.1", "karma-sauce-launcher": "0.2.0",
"karma-script-launcher": "~0.1.0", "karma-script-launcher": "0.1.0",
"karma-browserstack-launcher": "0.0.7",
"protractor": "~0.17.0",
"yaml-js": "~0.0.8", "yaml-js": "~0.0.8",
"marked": "0.2.9", "marked": "0.2.9",
"rewire": "1.1.3", "rewire": "1.1.3",
"grunt-jasmine-node": "git://github.com/vojtajina/grunt-jasmine-node.git#fix-grunt-exit-code",
"grunt-parallel": "~0.3.1",
"grunt-ddescribe-iit": "~0.0.1",
"grunt-merge-conflict": "~0.0.1",
"promises-aplus-tests": "~1.3.2", "promises-aplus-tests": "~1.3.2",
"grunt-shell": "~0.4.0",
"semver": "~2.1.0", "semver": "~2.1.0",
"lodash": "~2.1.0" "lodash": "~2.1.0",
"browserstacktunnel-wrapper": "~1.1.1"
}, },
"licenses": [ "licenses": [
{ {
@ -45,7 +51,5 @@
"url": "https://github.com/angular/angular.js/blob/master/LICENSE" "url": "https://github.com/angular/angular.js/blob/master/LICENSE"
} }
], ],
"dependencies": { "dependencies": {}
"grunt-contrib-jshint": "~0.6.4"
}
} }

31
protractor-conf.js Normal file
View file

@ -0,0 +1,31 @@
exports.config = {
allScriptsTimeout: 11000,
specs: [
'build/docs/ptore2e/**/*.js',
'test/e2e/docsAppE2E.js'
],
capabilities: {
'browserName': 'chrome'
},
baseUrl: 'http://localhost:8000/build/docs/',
framework: 'jasmine',
onPrepare: function() {
// Disable animations so e2e tests run more quickly
var disableNgAnimate = function() {
angular.module('disableNgAnimate', []).run(function($animate) {
$animate.enabled(false);
});
};
browser.addMockModule('disableNgAnimate', disableNgAnimate);
},
jasmineNodeOpts: {
defaultTimeoutInterval: 30000
}
};

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"

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
scripts/angular-seed/publish.sh Executable file
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

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

View file

@ -0,0 +1,42 @@
#!/bin/bash
# Tags a release
# so that travis can do the actual release.
echo "#################################"
echo "## Tag angular.js for a release #"
echo "#################################"
ARG_DEFS=(
"--action=(prepare|publish)"
"--commit-sha=(.*)"
# the version number of the release.
# e.g. 1.2.12 or 1.2.12-rc.1
"--version-number=([0-9]+\.[0-9]+\.[0-9]+(-[a-z]+\.[0-9]+)?)"
"--version-name=(.+)"
)
function checkVersionNumber() {
BRANCH_PATTERN=$(readJsonProp "package.json" "branchVersion")
if [[ $VERSION_NUMBER != $BRANCH_PATTERN ]]; then
echo "version-number needs to match $BRANCH_PATTERN on this branch"
usage
fi
}
function init {
cd ../..
checkVersionNumber
TAG_NAME="v$VERSION_NUMBER"
}
function prepare() {
git tag "$TAG_NAME" -m "chore(release): $TAG_NAME codename($VERSION_NAME)" "$COMMIT_SHA"
}
function publish() {
# push the tag to github
git push origin $TAG_NAME
}
source $(dirname $0)/../utils.inc

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

101
scripts/bower/publish.sh Executable file
View file

@ -0,0 +1,101 @@
#!/bin/bash
# Script for updating the Angular bower repos from current local build.
echo "#################################"
echo "#### Update bower ###############"
echo "#################################"
ARG_DEFS=(
"--action=(prepare|publish)"
)
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
)
}
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
#
# move the files from the build
#
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
# move i18n files
cp $BUILD_DIR/i18n/*.js $TMP_DIR/bower-angular-i18n/
# 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

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
scripts/jenkins/master.sh Executable file
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

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

71
scripts/jenkins/release.sh Executable file
View file

@ -0,0 +1,71 @@
#!/bin/bash
# tags the current commit as a release and publishes all artifacts to
# the different repositories.
# Note: This will also works if the commit is in the past!
echo "#################################"
echo "#### cut release ############"
echo "#################################"
ARG_DEFS=(
# require the git dryrun flag so the script can't be run without
# thinking about this!
"--git-push-dryrun=(true|false)"
# The sha to release. Needs to be the same as HEAD.
# given as parameter to double check.
"--commit-sha=(.*)"
# the version number of the release.
# e.g. 1.2.12 or 1.2.12-rc.1
"--version-number=([0-9]+\.[0-9]+\.[0-9]+(-[a-z]+\.[0-9]+)?)"
# the codename of the release
"--version-name=(.+)"
)
function init {
if [[ $(git rev-parse --short HEAD) != $COMMIT_SHA ]]; then
echo "HEAD is not at $COMMIT_SHA"
usage
fi
if [[ ! $VERBOSE ]]; then
VERBOSE=false
fi
VERBOSE_ARG="--verbose=$VERBOSE"
}
function build {
cd ../..
npm install --color false
grunt ci-checks package --no-color
cd $SCRIPT_DIR
}
function phase {
ACTION_ARG="--action=$1"
../angular.js/tag-release.sh $ACTION_ARG $VERBOSE_ARG\
--version-number=$VERSION_NUMBER --version-name=$VERSION_NAME\
--commit-sha=$COMMIT_SHA
if [[ $1 == "prepare" ]]; then
# The build requires the tag to be set already!
build
fi
../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=true
../angular-phonecat/publish.sh $ACTION_ARG $VERBOSE_ARG --no-test=true
}
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

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