Compare commits

..

289 Commits

Author SHA1 Message Date
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
Igor Minar 3efdeebcb7 chore(release): cut 1.2.2 consciousness-inertia release 2013-11-22 09:05:42 -08:00
Igor Minar 16febf8357 docs(CHANGELOG): add release notes for 1.2.2 consciousness-inertia 2013-11-22 09:03:40 -08:00
Caitlin Potter 0f7c4ca671 chore(style): fix missing indentation in httpBackend from a3172a2 2013-11-22 15:03:12 +00:00
Pete Bacon Darwin a3172a285f fix($httpBackend): only IE8 and below can't use script.onload for JSONP
IE8, IE9 and IE10 can use `script.onreadystate` so up till now we have been using this
if the sniffer says we are on IE.
But IE11 now does not support `script.onreadystate` and only supports the more standard
`script.onload` and `script.onerror`.
IE9 and IE10 do support `script.onload` and `script.onerror`. So now we only test whether
we are on IE8 or earlier before using `script.onreadystate`.
See http://pieisgood.org/test/script-link-events/

jQuery just uses all these handlers at once and hopes for the best, but since IE9 and IE10
support both sets of handlers, this could cause the handlers to be run more than once.

jQuery also notes that there is a potential memory leak in IE unless we remove the handlers
from the script object once they are run.  So we are doing this too, now.

Closes #4523
Closes #4527
Closes #4922
2013-11-22 13:45:55 +00:00
Igor Minar 84c408ce63 test($compile): correct the assertion to make test pass on IE11 2013-11-22 00:52:57 -08:00
rodyhaddad 40647b179c fix($parse): allow for new lines in expr when promise unwrapping is on
Previously, when unwrapping promises was set to `true`,
an error would occur if a parsed expression had a
new line in it.
This was because when generating the `evaledFnGetter` code,
a new line in an parsed expression would create a new line
in a JS string in that code, which is illegal. That is:
```js
pw("A+
B")
```

Closes #4718
2013-11-22 00:19:08 -08:00
Chirayu Krishnappa 0421cb4200 fix($compile): secure form[action] & iframe[srcdoc]
Require bindings to form[action] to be $sce.RESOURCE_URL and bindings to
iframe[srcdoc] to be $sce.HTML

Closes #4927
Closes #4933
2013-11-21 23:15:15 -08:00
Gonzalo Ruiz de Villa 6f1050df4f fix(httpBackend): should not read response data when request is aborted
When a request is aborted, it makes no sense to read the response headers or text.
Also in IE9, trying to read data (either response headers or text) from an aborted request
throws an Error c00c023f.

Fixes #4913
Closes #4940
2013-11-21 23:09:46 -08:00
Corey Burrows 4d16472b91 fix(ngMock): fixes httpBackend expectation with body object
Fixes an issue with httpBackend expectations where a given body object
may not match the actual request body if its keys are serialized in a
different order.

Closes #4956
2013-11-21 22:57:15 -08:00
Pete Bacon Darwin 9e89a31b12 fix(loader): expose $$minErr to modules such asngResource
This is highlighted in angular-phonecat when you try to use the index-async.html
which needs to load the ngResource module asynchronously but fails when it tries
to call `angular.$$minErr` to create the $resourceMinErr object.

Closes #5050
2013-11-21 22:51:26 -08:00
Tobias Bosch e6521e7491 fix(ngView): Don't throw when the ngView element contains content with directives.
Fixes #5069
2013-11-21 22:20:11 -08:00
Tobias Bosch 0a7cbb33b0 fix(ngInclude): Don't throw when the ngInclude element contains content with directives.
Related to #5069
2013-11-21 22:20:11 -08:00
Tobias Bosch 579242346c fix(tests): Correct tests for IE11
Some tests were wrong. However, src/* did not contain problems.

Fixes #5046
2013-11-21 21:53:09 -08:00
Peter Deak c42d0a0418 fix(ngAnimate): correctly retain and restore existing styles during and after animation
Closes #4869
2013-11-21 23:37:01 -05:00
Matias Niemelä 3fbb25e25c chore($animate): remove unnecessary reflective dereferencing 2013-11-21 20:48:21 -05:00
Matias Niemelä 6760d7a315 fix($animate): ensure keyframe animations are blocked around the reflow
Keyframe animations trigger on the first CSS class and not the second.
This may cause a slight flicker during a stagger animation since the
animation has already started before the stagger delay is considered.
This fix ensures that the animation is blocked until the active animation
starts which allows for staggering animations to take over properly.

Closes #5018
2013-11-21 20:48:15 -05:00
Matias Niemelä 062fbed8fc fix($animate): ensure transition animations are unblocked before the dom operation occurs
Transitions are blocked when the base CSS class is added at the start of the animation. This
causes an issue if the followup CSS class contains animatable-styles. Now, once the animation
active state is triggered (when the animation CSS dom operation occurs) the animation itself
will always trigger an animate without a quick jump.

Closes #5014
Closes #4265
2013-11-21 20:48:07 -05:00
Matias Niemelä 76e4db6f3d fix($animate): ensure addClass/removeClass animations do not snap during reflow
Closes #4892
2013-11-21 20:47:55 -05:00
Matias Niemelä 0cd7e8f227 fix($compile): ensure CSS classes are added and removed only when necessary
When $compile interpolates a CSS class attribute expression it will
do so by comparing the CSS class value already present on the element.
This may lead to unexpected results when dealing with ngClass values being
added and removed therefore it is best that both compile and ngClass delegate
addClass/removeClass operations to the same block of code.
2013-11-21 20:47:44 -05:00
Vojta Jina ba1b47f85b test(docs): fix the failing specs
Because Grunt was not failing the build, we didn't noticed these failing specs.
2013-11-21 12:41:57 -08:00
Vojta Jina 0a3481e23a chore: use temporary version of grunt-jasmine-node
This should be reverted once https://github.com/jasmine-contrib/grunt-jasmine-node/pull/33 gets merged in the upstream repo.

It fixes the problem where Grunt does not fail the build, even though there are failures.
See https://travis-ci.org/angular/angular.js/builds/14329011#L2366
2013-11-21 12:41:48 -08:00
jody tate e33c365144 docs(guide/unit-testing): minor style and grammar changes
Closes #5057
2013-11-21 20:37:57 +00:00
gdi2290 e3ceb50b73 docs(faq): update compressed and minified file size
Closes #5058
2013-11-21 20:27:27 +00:00
scottywakefield 6b5772bbbd docs(guide/ie): add info about what IE versions are supported
Added text from https://github.com/angular/angular.js/issues/4974

Closes #5070
2013-11-21 20:25:41 +00:00
Andrew Silluron-Gonzalez 6288cf5ca4 fix(ngController): fix issue with ngInclude on the same element
This changes the priority of ngController to 500 so that it takes precedence
over ngInclude.

Closes #4431, #4521
2013-11-21 09:52:34 -08:00
Tobias Bosch f6ecf9a3c9 fix($resource): Always return a resource instance when calling class methods on resources.
Previously, calling `MyResource.save(myResourceInstance)`returned
a promise, in contrast to the docs for `$resource`. However,
calling `MyResource.save({name: 'Tobias"})`already correctly
returned a resource instance.

Fixes #4545.
Closes #5061.
2013-11-21 09:51:02 -08:00
Chia-liang Kao a4e6d962d7 feat(input): hold listener during text composition
When composing text in CJKV, intermediate buffer for unfinished text should not
be updating the bound scope variables.

Closes #4684
2013-11-21 09:46:33 -08:00
Igor Minar 7874a4d007 docs(guide/migration): fix typo ngHtmlBind -> ngBindHtml 2013-11-21 07:29:18 -08:00
Matias Niemelä 1d50663b38 fix(ngAnimate): use a fallback CSS property that doesn't break existing styles
The clip property seems to remove the box-shadow property when an absolute
positioned animation is ongoing. This fix changes the property to be border-spacing
which is also very underused. The border-spacing CSS property is only visible
when border-collapse is set to separate.

Closes #4902
Closes #5030
2013-11-20 20:54:07 -05:00
Tobias Bosch ec3c4f94c7 refactor($sce): Use $sniffer instead of $document for feature detection.
Also adds `$sniffer.msieDocumentMode` property.

Closes #4931
Closes #5045
2013-11-20 23:12:39 +00:00
Matias Niemelä 6b8bbe4d90 fix(ngClass): ensure that ngClass only adds/removes the changed classes
ngClass works by removing all the former classes and then adding all the
new classes to the element during each watch change operation. This may
cause transition animations to never render. The ngClass directive will
now only add and remove the classes that change during each watch operation.

Closes #4960
Closes #4944
2013-11-20 17:15:56 -05:00
Matias Niemelä 7067a8fb0b fix($animate): ensure the DOM operation isn't run twice
Depending on the animations placed on ngClass, the DOM operation may
run twice causing a race condition between addClass and removeClass.
Depending on what classes are removed and added via $compile this may
cause all CSS classes to be removed accidentally from the element
being animated.

Closes #4949
2013-11-20 17:08:03 -05:00
Brian Ford c47abd0dd7 fix(ngInclude): allow ngInclude to load scripts when jQuery is included
In 1.2, the behavior of ngInclude was modified to use DOM APIs rather than jqLite. This means that
even when jQuery was loaded, ngInclude was not calling into it, and thus scripts were not eval'd
as they had been before. Although the use of ngInclude to eval scripts as a lazy-loading strategy
was never an intentional feature, this patch restores the ability to do so.

Closes #3756
2013-11-20 13:58:54 -08:00
Michel Salib 68d71bbc01 docs($log): the documented default log behavior was incorrect
Closes #4953
2013-11-20 21:02:02 +00:00
Jarrett Harris 334303e485 docs(ngAnimate): fixed two small typos
Line 162: 'defiend' should be 'defined'
Line 225: 'callback function be excuted' should be 'callback function will be executed'.

Closes #5048
2013-11-20 14:32:30 +00:00
gdennie b95fd53c6e docs(booleanAtts): explain the motivation for boolean attributes
It was not explicitly and consistently stated that the transient nature of boolean
attributes precludes them from hosting binding expressions.
This change make that more clear and reinforces the simplicity and elegance of the solution.

Closes #5031
2013-11-20 14:30:37 +00:00
Ashutosh Das c77dd040b4 docs(tutorial/step-2): correct the link to jasmine docs
Closes #5029
2013-11-20 14:21:49 +00:00
Stéphane Reynaud dc027f22e5 docs(ngRepeat): fix typo
Replace "ian" in "in"

Closes #5027
2013-11-20 14:10:23 +00:00
Stéphane Reynaud 043500fb27 docs(ngPluralize): Fix missing space before parentheses
There should be a space between "braces" and "(`{}`)"

Closes #5026
2013-11-20 11:38:29 +00:00
Maksim 3ceb6ab477 docs(guide/directive): use hideDialog handler in example
The handler is in the controller but was not being used in the template.

Closes #5020
2013-11-20 11:37:00 +00:00
gipsy86147 999fa44616 docs(guide/ie): fix typo
Closes #5006
2013-11-20 11:31:56 +00:00
Dave Gaeddert 5f9121ad56 docs(guide/providers): remove extra closing parenthesis in example
Closes #5005
2013-11-20 11:30:45 +00:00
Tyler Eich b4cf8483d7 docs(guide/migration): fix typo
Closes #5002
2013-11-20 11:26:57 +00:00
Yves Richard 8a9816e06b docs(guide/compiler): fix typo in isolate scope def
Closes #4999
2013-11-20 11:25:20 +00:00
jbnizet c0e10683a6 docs(api): example for $provide.value() uses $provide.value()
The example code for `$provide.value()` actually used `$provide.constant()`.
It now uses `$provide.value()`.

Closes #4983
Closes #4990
2013-11-20 11:21:09 +00:00
Pete Bacon Darwin cad5a367c3 docs(ngRoute): make it easier to find the example
Closes #4975
2013-11-20 11:18:21 +00:00
Stéphane Reynaud f2453eabb3 docs(tutorial): minimum node.js version is 0.10 (Windows too)
The doc has been modified by the following commit: bcc6e8d4f6
But the change was not made ​​for the part of Windows.

Closes #4967
2013-11-20 11:02:30 +00:00
Jayson Harshbarger aa0b11d794 docs(guide/migration): fix typo
Closes #4965
2013-11-20 11:00:01 +00:00
Matias Niemelä b9fa5c5a67 docs($animate): update the docs explaining enable/disable for specific elements 2013-11-19 17:50:24 -05:00
Vojta Jina 751f058f30 chore(travis): increase disconnect timeout
I still see some disconnection issues with IE9, hopefully this will help a bit.
2013-11-18 16:14:09 -08:00
Pete Bacon Darwin 29274e1d8d docs(ngApp): improve description and example 2013-11-18 16:21:59 +00:00
Jens Berthold 23ba287897 docs(guide/directive): clarify code example for isolated scopes bindings
Use different names for the attribute on the element (`info`) and the property (`customerInfo`)
on the isolate scope. Before `customer` was used for both which made it harder to understand.

Closes #4825
2013-11-18 15:03:35 +00:00
Pete Bacon Darwin 8f1e3606dd docs(guide/directive): add note about HTML case-insensitivity
Closes #4719
2013-11-18 12:58:53 +00:00
Chance ac56d1c9d9 docs(tutorial/step-4): controllers are no longer global functions
The docs did not line up with the codebase / previous steps of the tutorial.

Closes #4988
2013-11-18 12:49:19 +00:00
Pete Bacon Darwin de2919cb9a docs(guide/i18n): fix link to i18n files in the project
Closes #4998
2013-11-18 11:55:30 +00:00
Christoph Burgdorf 61943276f0 chore(*): remove accidentally created file
Closes #4963
2013-11-15 21:46:13 +00:00
Vojta Jina 88ce00a3cf chore(release): start a new release iteration 2013-11-15 00:03:03 -08:00
165 changed files with 8652 additions and 4963 deletions
+1
View File
@@ -17,3 +17,4 @@ angular.xcodeproj
libpeerconnection.log
npm-debug.log
/tmp/
/scripts/bower/bower-*
+9 -5
View File
@@ -3,11 +3,16 @@ node_js:
- 0.10
env:
matrix:
- JOB=unit
- JOB=e2e
global:
- SAUCE_USERNAME=angular-ci
- SAUCE_ACCESS_KEY=9b988f434ff8-fbca-8aa4-4ae3-35442987
- SAUCE_CONNECT_READY_FILE=/tmp/sauce-connect-ready
- BROWSER_STACK_USERNAME=VojtaJina
- BROWSER_STACK_ACCESS_KEY=HAfHZaypxAc3PEUrUU9a
- LOGS_DIR=/tmp/angular-build/logs
- BROWSER_PROVIDER_READY_FILE=/tmp/sauce-connect-ready
before_script:
- mkdir -p $LOGS_DIR
@@ -16,11 +21,10 @@ before_script:
- grunt bower
- grunt bower
- grunt package-without-bower
- grunt ci-checks
- ./lib/sauce/sauce_connect_block.sh
- ./scripts/travis/wait_for_browser_provider.sh
script:
- ./travis_build.sh
- ./scripts/travis/build.sh
after_script:
- ./travis_print_logs.sh
- ./scripts/travis/print_logs.sh
+345
View File
@@ -1,3 +1,345 @@
<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>
# 1.2.2 consciousness-inertia (2013-11-22)
## Bug Fixes
- **$animate:**
- ensure keyframe animations are blocked around the reflow
([6760d7a3](https://github.com/angular/angular.js/commit/6760d7a315d7ea5cbd4f8ab74b200f754a2041f4),
[#5018](https://github.com/angular/angular.js/issues/5018))
- ensure transition animations are unblocked before the dom operation occurs
([062fbed8](https://github.com/angular/angular.js/commit/062fbed8fc3f7bc55433f8c6915c27520e6f63c5),
[#5014](https://github.com/angular/angular.js/issues/5014),
[#4265](https://github.com/angular/angular.js/issues/4265))
- ensure addClass/removeClass animations do not snap during reflow
([76e4db6f](https://github.com/angular/angular.js/commit/76e4db6f3d15199ac1fbe85f9cfa6079a1c4fa56),
[#4892](https://github.com/angular/angular.js/issues/4892))
- ensure the DOM operation isn't run twice
([7067a8fb](https://github.com/angular/angular.js/commit/7067a8fb0b18d5b5489006e1960cee721a88b4d2),
[#4949](https://github.com/angular/angular.js/issues/4949))
- **$compile:**
- secure form[action] & iframe[srcdoc]
([0421cb42](https://github.com/angular/angular.js/commit/0421cb4200e672818ed10996e92311404c150c3a),
[#4927](https://github.com/angular/angular.js/issues/4927),
[#4933](https://github.com/angular/angular.js/issues/4933))
- ensure CSS classes are added and removed only when necessary
([0cd7e8f2](https://github.com/angular/angular.js/commit/0cd7e8f22721f62b62440bb059ae764ebbe7b42a))
- **$httpBackend:** only IE8 and below can't use `script.onload` for JSONP
([a3172a28](https://github.com/angular/angular.js/commit/a3172a285fd74b5aa6c8d68a4988c767c06f549c),
[#4523](https://github.com/angular/angular.js/issues/4523),
[#4527](https://github.com/angular/angular.js/issues/4527),
[#4922](https://github.com/angular/angular.js/issues/4922))
- **$parse:** allow for new lines in expr when promise unwrapping is on
([40647b17](https://github.com/angular/angular.js/commit/40647b179c473f3f470bb1b3237d6f006269582f),
[#4718](https://github.com/angular/angular.js/issues/4718))
- **$resource:** Always return a resource instance when calling class methods on resources.
([f6ecf9a3](https://github.com/angular/angular.js/commit/f6ecf9a3c9090593faf5fa50586c99a56b51c776),
[#4545](https://github.com/angular/angular.js/issues/4545),
[#5061](https://github.com/angular/angular.js/issues/5061))
- **httpBackend:** should not read response data when request is aborted
([6f1050df](https://github.com/angular/angular.js/commit/6f1050df4fa885bd59ce85adbef7350ea93911a3),
[#4913](https://github.com/angular/angular.js/issues/4913),
[#4940](https://github.com/angular/angular.js/issues/4940))
- **loader:** expose `$$minErr` to modules such as`ngResource`
([9e89a31b](https://github.com/angular/angular.js/commit/9e89a31b129e40c805178535c244899ffafb77d8),
[#5050](https://github.com/angular/angular.js/issues/5050))
- **ngAnimate:**
- correctly retain and restore existing styles during and after animation
([c42d0a04](https://github.com/angular/angular.js/commit/c42d0a041890b39fc98afd357ec1307a3a36208d),
[#4869](https://github.com/angular/angular.js/issues/4869))
- use a fallback CSS property that doesn't break existing styles
([1d50663b](https://github.com/angular/angular.js/commit/1d50663b38ba042e8d748ffa6d48cfb5e93cfd7e),
[#4902](https://github.com/angular/angular.js/issues/4902),
[#5030](https://github.com/angular/angular.js/issues/5030))
- **ngClass:** ensure that ngClass only adds/removes the changed classes
([6b8bbe4d](https://github.com/angular/angular.js/commit/6b8bbe4d90640542eed5607a8c91f6b977b1d6c0),
[#4960](https://github.com/angular/angular.js/issues/4960),
[#4944](https://github.com/angular/angular.js/issues/4944))
- **ngController:** fix issue with ngInclude on the same element
([6288cf5c](https://github.com/angular/angular.js/commit/6288cf5ca471b0615a026fdb4db3ba242c9d8f88),
[#4431](https://github.com/angular/angular.js/issues/4431))
- **ngInclude:**
- Don't throw when the ngInclude element contains content with directives.
([0a7cbb33](https://github.com/angular/angular.js/commit/0a7cbb33b06778833a4d99b1868cc07690a827a7))
- allow ngInclude to load scripts when jQuery is included
([c47abd0d](https://github.com/angular/angular.js/commit/c47abd0dd7490576f4b84ee51ebaca385c1036da),
[#3756](https://github.com/angular/angular.js/issues/3756))
- **ngMock:** fixes httpBackend expectation with body object
([4d16472b](https://github.com/angular/angular.js/commit/4d16472b918a3482942d76f1e273a5aa01f65e83),
[#4956](https://github.com/angular/angular.js/issues/4956))
- **ngView:** Don't throw when the ngView element contains content with directives.
([e6521e74](https://github.com/angular/angular.js/commit/e6521e7491242504250b57dd0ee66af49e653c33),
[#5069](https://github.com/angular/angular.js/issues/5069))
- **tests:** Correct tests for IE11
([57924234](https://github.com/angular/angular.js/commit/579242346c4202ea58fc2cae6df232289cbea0bb),
[#5046](https://github.com/angular/angular.js/issues/5046))
- **input:** hold listener during text composition
([a4e6d962](https://github.com/angular/angular.js/commit/a4e6d962d78b26f5112d48c4f88c1e6234d0cae7),
[#4684](https://github.com/angular/angular.js/issues/4684))
<a name="1.2.1"></a>
# 1.2.1 underscore-empathy (2013-11-14)
@@ -4110,3 +4452,6 @@ with the `$route` service
[module]: http://docs-next.angularjs.org/api/angular.mock.module
[guide2.di]: http://docs-next.angularjs.org/guide/dev_guide.di
[jqLite2]: http://docs.angularjs.org/#!/api/angular.element
[![Analytics](https://ga-beacon.appspot.com/UA-8594346-11/angular.js/CHANGELOG.md?pixel)](https://github.com/igrigorik/ga-beacon)
+111 -64
View File
@@ -29,32 +29,124 @@ duplication of work, and help you to craft the change so that it is successfully
project.
* **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
### Submitting an Issue
Before you submit your issue follow the following guidelines:
* 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!
Before you submit your issue search the archive, maybe your question was already answered.
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
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
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
to duplicate effort.
* Search [GitHub](https://github.com/angular/angular.js/pulls) for an open or closed Pull Request
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
```shell
git checkout -b my-fix-branch master
```
* Create your patch, including appropriate test cases.
* Follow our Coding Rules
* Follow our Git Commit Guidelines
* Build your changes locally and on Travis (by pushing to GitHub) to ensure all the tests pass.
* Sign the Contributor License Agreement (CLA). We cannot accept code without this.
* 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
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
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
semi-colons, etc)
* **refactor**: A code change that neither fixes a bug or adds a feature
* **perf**: A code change that improves performance
* **test**: Adding missing tests
* **chore**: Changes to the build process or auxiliary tools and libraries such as documentation
generation
@@ -146,56 +239,6 @@ You can find out more detailed information about contributing in the
[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
[Google Closure I18N library]: https://code.google.com/p/closure-library/source/browse/closure/goog/i18n/
@@ -214,3 +257,7 @@ git pull --ff upstream master
[individual-cla]: http://code.google.com/legal/individual-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#
[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)
+15 -12
View File
@@ -4,6 +4,7 @@ var path = require('path');
module.exports = function(grunt) {
//grunt plugins
grunt.loadNpmTasks('grunt-bump');
grunt.loadNpmTasks('grunt-contrib-clean');
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.loadNpmTasks('grunt-contrib-connect');
@@ -106,45 +107,38 @@ module.exports = function(grunt) {
},
jshint: {
options: {
jshintrc: true,
},
ng: {
files: { src: files['angularSrc'] },
options: { jshintrc: 'src/.jshintrc' }
},
ngAnimate: {
files: { src: 'src/ngAnimate/**/*.js' },
options: { jshintrc: 'src/ngAnimate/.jshintrc' }
},
ngCookies: {
files: { src: 'src/ngCookies/**/*.js' },
options: { jshintrc: 'src/ngCookies/.jshintrc' }
},
ngLocale: {
files: { src: 'src/ngLocale/**/*.js' },
options: { jshintrc: 'src/ngLocale/.jshintrc' }
},
ngMock: {
files: { src: 'src/ngMock/**/*.js' },
options: { jshintrc: 'src/ngMock/.jshintrc' }
},
ngResource: {
files: { src: 'src/ngResource/**/*.js' },
options: { jshintrc: 'src/ngResource/.jshintrc' }
},
ngRoute: {
files: { src: 'src/ngRoute/**/*.js' },
options: { jshintrc: 'src/ngRoute/.jshintrc' }
},
ngSanitize: {
files: { src: 'src/ngSanitize/**/*.js' },
options: { jshintrc: 'src/ngSanitize/.jshintrc' }
},
ngScenario: {
files: { src: 'src/ngScenario/**/*.js' },
options: { jshintrc: 'src/ngScenario/.jshintrc' }
},
ngTouch: {
files: { src: 'src/ngTouch/**/*.js' },
options: { jshintrc: 'src/ngTouch/.jshintrc' }
}
},
@@ -178,7 +172,7 @@ module.exports = function(grunt) {
},
mocks: {
dest: 'build/angular-mocks.js',
src: files['angularModules']['ngMock'],
src: util.wrap(files['angularModules']['ngMock'], 'module'),
strict: false
},
sanitize: {
@@ -275,6 +269,15 @@ module.exports = function(grunt) {
write: {
versionTXT: {file: 'build/version.txt', val: NG_VERSION.full},
versionJSON: {file: 'build/version.json', val: JSON.stringify(NG_VERSION)}
},
bump: {
options: {
files: ['package.json'],
commit: false,
createTag: false,
push: false
}
}
});
@@ -294,6 +297,6 @@ module.exports = function(grunt) {
grunt.registerTask('webserver', ['connect:devserver']);
grunt.registerTask('package', ['bower','clean', 'buildall', 'minall', 'collect-errors', 'docs', 'copy', 'write', 'compress']);
grunt.registerTask('package-without-bower', ['clean', 'buildall', 'minall', 'collect-errors', 'docs', 'copy', 'write', 'compress']);
grunt.registerTask('ci-checks', ['ddescribe-iit', 'merge-conflict', 'jshint', 'test:docgen']);
grunt.registerTask('ci-checks', ['ddescribe-iit', 'merge-conflict', 'jshint']);
grunt.registerTask('default', ['package']);
};
+4
View File
@@ -38,3 +38,7 @@ To execute end-to-end (e2e) tests, use:
To learn more about the grunt tasks, run `grunt --help` and also read our
[contribution guidelines](http://docs.angularjs.org/misc/contribute).
[![Analytics](https://ga-beacon.appspot.com/UA-8594346-11/angular.js/README.md?pixel)](https://github.com/igrigorik/ga-beacon)
+63
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 welcome" for "GH: issue"
* if complexity is small or medium and the problem as well as solution are well captured in the issue
1. Label "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
View File
@@ -27,6 +27,7 @@ angularFiles = {
'src/ng/parse.js',
'src/ng/q.js',
'src/ng/rootScope.js',
'src/ng/sanitizeUri.js',
'src/ng/sce.js',
'src/ng/sniffer.js',
'src/ng/timeout.js',
+3 -1
View File
@@ -142,6 +142,7 @@ var writeChangelog = function(stream, commits, version) {
var sections = {
fix: {},
feat: {},
perf: {},
breaks: {}
};
@@ -169,6 +170,7 @@ var writeChangelog = function(stream, commits, version) {
stream.write(util.format(HEADER_TPL, version, version, currentDate()));
printSection(stream, 'Bug Fixes', sections.fix);
printSection(stream, 'Features', sections.feat);
printSection(stream, 'Performance Improvements', sections.perf);
printSection(stream, 'Breaking Changes', sections.breaks, false);
}
@@ -186,7 +188,7 @@ var getPreviousTag = function() {
var generate = function(version, file) {
getPreviousTag().then(function(tag) {
console.log('Reading git log since', tag);
readGitLog('^fix|^feat|BREAKING', tag).then(function(commits) {
readGitLog('^fix|^feat|^perf|BREAKING', tag).then(function(commits) {
console.log('Parsed', commits.length, 'commits');
console.log('Generating changelog to', file || 'stdout', '(', version, ')');
writeChangelog(file ? fs.createWriteStream(file) : process.stdout, commits, version);
-80
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))
+66 -3
View File
@@ -225,6 +225,11 @@ angular.uppercase = function(s) {};
*/
angular.Attributes;
/**
* @type {Object.<string, string>}
*/
angular.Attributes.$attr;
/**
* @param {string} name
* @return {string}
@@ -757,7 +762,9 @@ angular.Module.requires;
* $parent: angular.Scope,
* $root: angular.Scope,
* $watch: function(
* (string|Function), (string|Function)=, boolean=):function()
* (string|Function), (string|Function)=, boolean=):function(),
* $watchCollection: function(
* (string|Function), (string|Function)=):function()
* }}
*/
angular.Scope;
@@ -829,6 +836,13 @@ angular.Scope.$root;
*/
angular.Scope.$watch = function(exp, opt_listener, opt_objectEquality) {};
/**
* @param {string|Function} exp
* @param {(string|Function)=} opt_listener
* @return {function()}
*/
angular.Scope.$watchCollection = function(exp, opt_listener) {};
/**
* @typedef {{
* currentScope: angular.Scope,
@@ -1048,6 +1062,10 @@ angular.$http;
*/
angular.$http.Config;
angular.$http.Config.transformRequest;
angular.$http.Config.transformResponse;
// /**
// * This extern is currently incomplete as delete is a reserved word.
// * To use delete, index $http.
@@ -1154,6 +1172,13 @@ angular.$http.HttpPromise.error = function(callback) {};
*/
angular.$http.Response;
angular.$HttpProvider;
/**
* @type {angular.$http.Config}
*/
angular.$HttpProvider.defaults;
/******************************************************************************
* $injector Service
*****************************************************************************/
@@ -1425,6 +1450,11 @@ angular.NgModelController.prototype.$viewValue;
*/
angular.FormController = function() {};
/**
* @param {*} control
*/
angular.FormController.prototype.$addControl = function(control) {};
/**
* @type {boolean}
*/
@@ -1440,11 +1470,39 @@ angular.FormController.prototype.$error;
*/
angular.FormController.prototype.$invalid;
/**
* @type {string}
*/
angular.FormController.prototype.$name;
/**
* @type {boolean}
*/
angular.FormController.prototype.$pristine;
/**
* @param {*} control
*/
angular.FormController.prototype.$removeControl = function(control) {};
/**
* @type {function()}
*/
angular.FormController.prototype.$setDirty = function() {};
/**
* @type {function()}
*/
angular.FormController.prototype.$setPristine = function() {};
/**
* @param {string} validationToken
* @param {boolean} isValid
* @param {*} control
*/
angular.FormController.prototype.$setValidity = function(
validationToken, isValid, control) {};
/**
* @type {boolean}
*/
@@ -1578,6 +1636,7 @@ angular.$q.when = function(value) {};
* @typedef {{
* resolve: function(*=),
* reject: function(*=),
* notify: function(*=),
* promise: angular.$q.Promise
* }}
*/
@@ -1589,6 +1648,9 @@ angular.$q.Deferred.resolve = function(opt_value) {};
/** @param {*=} opt_reason */
angular.$q.Deferred.reject = function(opt_reason) {};
/** @param {*=} opt_value */
angular.$q.Deferred.notify = function(opt_value) {};
/** @type {angular.$q.Promise} */
angular.$q.Deferred.promise;
@@ -1689,7 +1751,8 @@ angular.$routeProvider.when = function(path, route) {};
* resolve: (Object.<string, (
* string|Function|Array.<string|Function>|angular.$q.Promise
* )>|undefined),
* redirectTo: (string|function()|undefined),
* redirectTo: (
* string|function(Object.<string>, string, Object): string|undefined),
* reloadOnSearch: (boolean|undefined)
* }}
*/
@@ -1712,7 +1775,7 @@ angular.$routeProvider.Params.templateUrl;
*/
angular.$routeProvider.Params.resolve;
/** @type {string|function()} */
/** @type {string|function(Object.<string>, string, Object): string} */
angular.$routeProvider.Params.redirectTo;
/** @type {boolean} */
-11
View File
@@ -9,14 +9,3 @@
ng\:form {
display: block;
}
/* The styles below ensure that the CSS transition will ALWAYS
* animate and close. A nasty bug occurs with CSS transitions where
* when the active class isn't set, or if the active class doesn't
* contain any styles to transition to, then, if ngAnimate is used,
* it will appear as if the webpage is broken due to the forever hanging
* animations. The clip (!ie) and zoom (ie) CSS properties are used
* since they trigger a transition without making the browser
* animate anything and they're both highly underused CSS properties */
.ng-animate-start { clip:rect(0, auto, auto, 0); -ms-zoom:1.0001; }
.ng-animate-active { clip:rect(-1px, auto, auto, 0); -ms-zoom:1; }
+1 -1
View File
@@ -5,7 +5,7 @@ describe('Docs Annotations', function() {
var body;
beforeEach(function() {
body = angular.element(document.body);
body.html('');
body.empty();
});
var normalizeHtml = function(html) {
+2 -12
View File
@@ -28,7 +28,7 @@ function escape(text) {
function setHtmlIe8SafeWay(element, html) {
var newElement = angular.element('<pre>' + html + '</pre>');
element.html('');
element.empty();
element.append(newElement.contents());
return element;
}
@@ -215,17 +215,7 @@ directive.ngEmbedApp = ['$templateCache', '$browser', '$rootScope', '$location',
}];
this.html5Mode = angular.noop;
});
$provide.decorator('$timeout', ['$rootScope', '$delegate', function($rootScope, $delegate) {
return angular.extend(function(fn, delay) {
if (delay && delay > 50) {
return setTimeout(function() {
$rootScope.$apply(fn);
}, delay);
} else {
return $delegate.apply(this, arguments);
}
}, $delegate);
}]);
$provide.decorator('$rootScope', ['$delegate', function($delegate) {
embedRootScope = $delegate;
+4 -1
View File
@@ -3,6 +3,9 @@
@description
# ng (core module)
The ng module is loaded by default when an AngularJS application is started. The module itself contains the essential components to for an AngularJS application to function. The table below lists a high level breakdown of each of the services/factories, filters, directives and testing components available within this core module.
The ng module is loaded by default when an AngularJS application is started. The module itself
contains the essential components for an AngularJS application to function. The table below
lists a high level breakdown of each of the services/factories, filters, directives and testing
components available within this core module.
<div doc-module-components="ng"></div>
@@ -1,9 +0,0 @@
@ngdoc error
@name $httpBackend:noxhr
@fullName Unsupported XHR
@description
This error occurs in browsers that do not support XmlHttpRequest. AngularJS
supports Safari, Chrome, Firefox, Opera, IE8 and higher, and mobile browsers
(Android, Chrome Mobile, iOS Safari). To avoid this error, use an officially
supported browser.
+1 -1
View File
@@ -4,4 +4,4 @@
@description
This error occurs when 'ngPattern' is passed an expression that isn't a regular expression or doesn't have the expected format.
For more information on valid expression syntax, see 'ngPattern' in {@link api/ng.directive:select input} directive docs.
For more information on valid expression syntax, see 'ngPattern' in {@link api/ng.directive:input input} directive docs.
+1 -1
View File
@@ -13,7 +13,7 @@ For example the issue can be triggered by this *invalid* code:
<div ng-repeat="value in [4, 4]"></div>
```
To resolve this error either ensure that the items in the collection have unique identity of use the `track by` syntax to specify how to track the association between models and DOM.
To resolve this error either ensure that the items in the collection have unique identity or use the `track by` syntax to specify how to track the association between models and DOM.
To resolve the example above can be resolved by using `track by $index`, which will cause the items to be keyed by their position in the array instead of their value:
+2 -2
View File
@@ -3,9 +3,9 @@
@fullName Orphan ngTransclude Directive
@description
Occurs when an `ngTransclude` occurs without a transcluded ancesstor element.
Occurs when an `ngTransclude` occurs without a transcluded ancestor element.
This error often occurs when you have forgotten to set `transclude: true` in some directive definition, and then used `ngTranslude` in the driective's template.
This error often occurs when you have forgotten to set `transclude: true` in some directive definition, and then used `ngTransclude` in the directive's template.
To resolve, either remove the offending `ngTransclude` or check that `transclude: true` is included in the intended directive definition.
+6 -2
View File
@@ -190,6 +190,7 @@ This should help give you an idea of what Angular does internally.
<pre>
var $compile = ...; // injected into your code
var scope = ...;
var parent = ...; // DOM element where the compiled template can be appended
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);
// 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>
### The difference between Compile and Link
@@ -350,7 +354,7 @@ Creating local properties on widget scope creates two problems:
To solve the issue of lack of isolation, the directive declares a new `isolated` scope. An
isolated scope does not prototypically inherit from the child scope, and therefore we don't have
isolated scope does not prototypically inherit from the parent scope, and therefore we don't have
to worry about accidentally clobbering any properties.
However `isolated` scope creates a new problem: if a transcluded DOM is a child of the widget
+1 -1
View File
@@ -270,7 +270,7 @@ 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.
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.
The code snippet `angular.module('invoice', ['finance'])` specifies that the `invoice` module depends on the
`finance` module. By this, Angular uses the `InvoiceController` as well as the `currencyConverter` service.
@@ -50,7 +50,7 @@ of which depend on other services that are provided by the Angular framework:
* @param {*} message Message to be logged.
*/
function batchLogModule($provide){
$provide.factory('batchLog', ['$timeout', '$log', function($timeout, $log) {
$provide.factory('batchLog', ['$interval', '$log', function($interval, $log) {
var messageQueue = [];
function log() {
@@ -58,11 +58,10 @@ of which depend on other services that are provided by the Angular framework:
$log('batchLog messages: ', messageQueue);
messageQueue = [];
}
$timeout(log, 50000);
}
// start periodic checking
log();
$interval(log, 50000);
return function(message) {
messageQueue.push(message);
@@ -82,13 +81,13 @@ of which depend on other services that are provided by the Angular framework:
}]);
}
// get the main service to kick of the application
// get the main service to kick off the application
angular.injector([batchLogModule]).get('routeTemplateMonitor');
</pre>
Things to notice in this example:
* The `batchLog` service depends on the built-in {@link api/ng.$timeout $timeout} and
* The `batchLog` service depends on the built-in {@link api/ng.$interval $interval} and
{@link api/ng.$log $log} services, and allows messages to be logged into the
`console.log` in batches.
* The `routeTemplateMonitor` service depends on the built-in {@link api/ngRoute.$route
+50 -51
View File
@@ -13,45 +13,44 @@ Unit testing as the name implies is about testing individual units of code. Unit
answer questions such as "Did I think about the logic correctly?" or "Does the sort function order the list
in the right order?"
In order to answer such question it is very important that we can isolate the unit of code under test.
In order to answer such a question it is very important that we can isolate the unit of code under test.
That is because when we are testing the sort function we don't want to be forced into creating
related pieces such as the DOM elements, or making any XHR calls in getting the data to sort.
While
this may seem obvious it usually is very difficult to be able to call an individual function on a
typical project. The reason is that the developers often mix concerns, and they end up with a
piece of code which does everything. It reads the data from XHR, it sorts it and then it
While this may seem obvious it can be very difficult to call an individual function on a
typical project. The reason is that the developers often mix concerns resulting in a
piece of code which does everything. It makes an XHR request, it sorts the response data and then it
manipulates the DOM.
With Angular we try to make it easy for you to do the right thing, and so we
provide dependency injection for your XHR (which you can mock out) and we created abstraction which
provide dependency injection for your XHR (which you can mock out) and we created abstractions which
allow you to sort your model without having to resort to manipulating the DOM. So that in the end,
it is easy to write a sort function which sorts some data, so that your test can create a data set,
apply the function, and assert that the resulting model is in the correct order. The test does not
have to wait for XHR, or create the right kind of DOM, or assert that your function has mutated the
DOM in the right way.
have to wait for the XHR response to arrive, create the right kind of test DOM, nor assert that your
function has mutated the DOM in the right way.
## With great power comes great responsibility
Angular is written with testability in mind, but it still requires that you
do the right thing. We tried to make the right thing easy, but Angular is not magic, which means if
you don't follow these guidelines you may very well end up with an untestable application.
Angular is written with testability in mind, but it still requires that you do the right thing.
We tried to make the right thing easy, but Angular is not magic. If you don't follow these guidelines
you may very well end up with an untestable application.
## Dependency Injection
There are several ways in which you can get a hold of a dependency:
1. You could create it using the `new` operator.
2. You could look for it in a well known place, also known as global singleton.
3. You could ask a registry (also known as service registry) for it. (But how do you get a hold of
the registry? Most likely by looking it up in a well known place. See #2)
4. You could expect that it be handed to you.
There are several ways in which you can get a hold of a dependency. You can:
1. Create it using the `new` operator.
2. Look for it in a well-known place, also known as a global singleton.
3. Ask a registry (also known as service registry) for it. (But how do you get a hold of
the registry? Most likely by looking it up in a well known place. See #2.)
4. Expect it to be handed to you.
Out of the four options in the list above, only the last one is testable. Let's look at why:
### Using the `new` operator
While there is nothing wrong with the `new` operator fundamentally the issue is that calling a new
on a constructor permanently binds the call site to the type. For example lets say that we are
trying to instantiate an `XHR` so that we can get some data from the server.
While there is nothing wrong with the `new` operator fundamentally, a problem arises when calling `new`
on a constructor. This permanently binds the call site to the type. For example, lets say that we try to
instantiate an `XHR` that will retrieve data from the server.
<pre>
function MyClass() {
@@ -64,12 +63,12 @@ function MyClass() {
}
</pre>
The issue becomes that in tests, we would very much like to instantiate a `MockXHR` which would
A problem surfaces in tests when we would like to instantiate a `MockXHR` that would
allow us to return fake data and simulate network failures. By calling `new XHR()` we are
permanently bound to the actual XHR, and there is no good way to replace it. Yes there is monkey
patching. That is a bad idea for many reasons which are outside the scope of this document.
permanently bound to the actual XHR and there is no way to replace it. Yes, we could monkey
patch, but that is a bad idea for many reasons which are outside the scope of this document.
The class above is hard to test since we have to resort to monkey patching:
Here's an example of how the class above becomes hard to test when resorting to monkey patching:
<pre>
var oldXHR = XHR;
XHR = function MockXHR() {};
@@ -81,7 +80,7 @@ XHR = oldXHR; // if you forget this bad things will happen
### Global look-up:
Another way to approach the problem is to look for the service in a well known location.
Another way to approach the problem is to look for the service in a well-known location.
<pre>
function MyClass() {
@@ -95,14 +94,14 @@ function MyClass() {
}
</pre>
While no new instance of the dependency is being created, it is fundamentally the same as `new`, in
that there is no good way to intercept the call to `global.xhr` for testing purposes, other then
While no new dependency instance is created, it is fundamentally the same as `new` in
that no way exists to intercept the call to `global.xhr` for testing purposes, other then
through monkey patching. The basic issue for testing is that a global variable needs to be mutated in
order to replace it with call to a mock method. For further explanation why this is bad see: {@link
order to replace it with call to a mock method. For further explanation of why this is bad see: {@link
http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/ Brittle Global
State & Singletons}
The class above is hard to test since we have to change global state:
The class above is hard to test since we have to change the global state:
<pre>
var oldXHR = global.xhr;
global.xhr = function mockXHR() {};
@@ -115,7 +114,7 @@ global.xhr = oldXHR; // if you forget this bad things will happen
### Service Registry:
It may seem as that this can be solved by having a registry for all of the services, and then
It may seem that this can be solved by having a registry of all the services and then
having the tests replace the services as needed.
<pre>
@@ -131,12 +130,12 @@ function MyClass() {
}
</pre>
However, where does the serviceRegistry come from? if it is:
* `new`-ed up, the test has no chance to reset the services for testing
* global look-up, then the service returned is global as well (but resetting is easier, since
there is only one global variable to be reset).
However, where does the serviceRegistry come from? If it is:
* `new`-ed up, the test has no chance to reset the services for testing.
* a global look-up then the service returned is global as well (but resetting is easier, since
only one global variable exists to be reset).
The class above is hard to test since we have to change global state:
The class above is hard to test since we have to change the global state:
<pre>
var oldServiceLocator = global.serviceLocator;
global.serviceLocator.set('xhr', function mockXHR() {});
@@ -148,7 +147,7 @@ global.serviceLocator = oldServiceLocator; // if you forget this bad things will
### Passing in Dependencies:
Lastly the dependency can be passed in.
Last, the dependency can be passed in.
<pre>
function MyClass(xhr) {
@@ -161,12 +160,12 @@ function MyClass(xhr) {
}
</pre>
This is the preferred way since the code makes no assumptions as to where the `xhr` comes from,
rather that whoever created the class was responsible for passing it in. Since the creator of the
This is the preferred method since the code makes no assumptions about the origin of `xhr` and cares
instead about whoever created the class responsible for passing it in. Since the creator of the
class should be different code than the user of the class, it separates the responsibility of
creation from the logic, and that is what dependency-injection is in a nutshell.
creation from the logic. This is dependency-injection in a nutshell.
The class above is very testable, since in the test we can write:
The class above is testable, since in the test we can write:
<pre>
function xhrMock(args) {...}
var myClass = new MyClass(xhrMock);
@@ -176,12 +175,12 @@ myClass.doWork();
Notice that no global variables were harmed in the writing of this test.
Angular comes with {@link di dependency injection} built in which makes the right thing
Angular comes with {@link di dependency injection} built-in, making the right thing
easy to do, but you still need to do it if you wish to take advantage of the testability story.
## Controllers
What makes each application unique is its logic, which is what we would like to test. If the logic
for your application is mixed in with DOM manipulation, it will be hard to test as in the example
What makes each application unique is its logic, and the logic is what we would like to test. If the logic
for your application contains DOM manipulation, it will be hard to test. See the example
below:
<pre>
@@ -209,7 +208,7 @@ function PasswordCtrl() {
}
</pre>
The code above is problematic from a testability point of view, since it requires your test to have the right kind
The code above is problematic from a testability point of view since it requires your test to have the right kind
of DOM present when the code executes. The test would look like this:
<pre>
@@ -223,11 +222,11 @@ var pc = new PasswordCtrl();
input.val('abc');
pc.grade();
expect(span.text()).toEqual('weak');
$('body').html('');
$('body').empty();
</pre>
In angular the controllers are strictly separated from the DOM manipulation logic which results in
a much easier testability story as can be seen in this example:
In angular the controllers are strictly separated from the DOM manipulation logic and this results in
a much easier testability story as the following example shows:
<pre>
function PasswordCtrl($scope) {
@@ -245,7 +244,7 @@ function PasswordCtrl($scope) {
}
</pre>
and the test is straight forward
and the test is straight forward:
<pre>
var $scope = {};
@@ -255,11 +254,11 @@ $scope.grade();
expect($scope.strength).toEqual('weak');
</pre>
Notice that the test is not only much shorter but it is easier to follow what is going on. We say
Notice that the test is not only much shorter, it is also easier to follow what is happening. We say
that such a test tells a story, rather then asserting random bits which don't seem to be related.
## Filters
{@link api/ng.$filterProvider Filters} are functions which transform the data into user readable
{@link api/ng.$filterProvider Filters} are functions which transform the data into a user readable
format. They are important because they remove the formatting responsibility from the application
logic, further simplifying the application logic.
@@ -282,7 +281,7 @@ you create with directives may be used throughout your application and in many d
### Simple HTML Element Directive
Lets start with an angular app with no dependencies.
Let's start with an angular app with no dependencies.
<pre>
var app = angular.module('myApp', []);
+1 -1
View File
@@ -146,7 +146,7 @@ of service names to inject.
var MyController = function(renamed$scope, renamedGreeter) {
...
}
MyController.$inject = ['$scope', 'greeter'];
MyController['$inject'] = ['$scope', 'greeter'];
</pre>
In this scenario the ordering of the values in the '$inject' array must match the ordering of the arguments to inject.
+38 -37
View File
@@ -56,9 +56,9 @@ The following also **matches** `ngModel`:
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
{@link http://en.wikipedia.org/wiki/CamelCase camelCase} **normalized** name (e.g. `ngModel`).
However, in the DOM, we refer to directives by case-insensitive forms, typically using
{@link http://en.wikipedia.org/wiki/Letter_case#Computers dash-delimited} attributes on DOM elements
(e.g. `ng-model`).
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}
attributes on DOM elements (e.g. `ng-model`).
The **normalization** process is as follows:
@@ -404,40 +404,43 @@ we call an **isolate scope**. To do this, we can use a directive's `scope` optio
return {
restrict: 'E',
scope: {
customer: '=customer'
customerInfo: '=info'
},
templateUrl: 'my-customer.html'
templateUrl: 'my-customer-iso.html'
};
});
</file>
<file name="index.html">
<div ng-controller="Ctrl">
<my-customer customer="naomi"></my-customer>
<my-customer info="naomi"></my-customer>
<hr>
<my-customer customer="igor"></my-customer>
<my-customer info="igor"></my-customer>
</div>
</file>
<file name="my-customer.html">
Name: {{customer.name}} Address: {{customer.address}}
<file name="my-customer-iso.html">
Name: {{customerInfo.name}} Address: {{customerInfo.address}}
</file>
</example>
Looking at `index.html`, the first `<my-customer>` element binds the inner scope's `customer` to
`naomi`, which we have exposed on our controller's scope. The second binds `customer` to `igor`.
Looking at `index.html`, the first `<my-customer>` element binds the `info` attribute to `naomi`,
which we have exposed on our controller's scope. The second binds `info` to `igor`.
Let's take a closer look at the scope option:
```javascript
//...
scope: {
customer: '=customer'
customerInfo: '=info'
},
//...
```
The property name (`customer`) corresponds to the variable name of the `myCustomer` directive's
isolated scope. The value of the property (`=customer`) tells `$compile` to bind to the `customer`
attribute.
The **scope option** is an object that contains a property for each isolate scope binding. In this
case it has just one property:
- Its name (`customerInfo`) corresponds to the
directive's **isolate scope** property `customerInfo`.
- Its value (`=info`) tells `$compile` to bind to the `info` attribute.
<div class="alert alert-warning">
**Note:** These `=attr` attributes in the `scope` option of directives are normalized just like
@@ -449,12 +452,12 @@ For cases where the attribute name is the same as the value you want to bind to
directive's scope, you can use this shorthand syntax:
```javascript
//...
...
scope: {
// same as '=customer'
// same as '=customer'
customer: '='
},
//...
...
```
Besides making it possible to bind different data to the scope inside a directive, using an isolated
@@ -475,7 +478,7 @@ within our directive's template:
return {
restrict: 'E',
scope: {
customer: '=customer'
customerInfo: '=info'
},
templateUrl: 'my-customer-plus-vojta.html'
};
@@ -483,11 +486,11 @@ within our directive's template:
</file>
<file name="index.html">
<div ng-controller="Ctrl">
<my-customer customer="naomi"></my-customer>
<my-customer info="naomi"></my-customer>
</div>
</file>
<file name="my-customer-plus-vojta.html">
Name: {{customer.name}} Address: {{customer.address}}
Name: {{customerInfo.name}} Address: {{customerInfo.address}}
<hr>
Name: {{vojta.name}} Address: {{vojta.address}}
</file>
@@ -503,6 +506,8 @@ that you explicitly pass in.
<div class="alert alert-warning">
**Note:** Normally, a scope prototypically inherits from its parent. An isolated scope does not.
See the {@link guide/directive#creating-custom-directives_demo_isolating-the-scope-of-a-directive
"Isolating the Scope of a Directive"} section for more information about isolate scopes.
</div>
<div class="alert alert-success">
@@ -525,8 +530,10 @@ where:
* `attrs` is an object with the normalized attribute names and their corresponding values.
In our `link` function, we want to update the displayed time once a second, or whenever a user
changes the time formatting string that our directive binds to. We also want to remove the timeout
if the directive is deleted so we don't introduce a memory leak.
changes the time formatting string that our directive binds to. We will use the `$interval` service
to call a handler on a regular basis. This is easier than using `$timeout` but also works better with
end 2 end testing, where we want to ensure that all $timeouts have completed before completing the test.
We also want to remove the `$interval` if the directive is deleted so we don't introduce a memory leak.
<example module="docsTimeDirective">
<file name="script.js">
@@ -534,7 +541,7 @@ if the directive is deleted so we don't introduce a memory leak.
.controller('Ctrl2', function($scope) {
$scope.format = 'M/d/yy h:mm:ss a';
})
.directive('myCurrentTime', function($timeout, dateFilter) {
.directive('myCurrentTime', function($interval, dateFilter) {
function link(scope, element, attrs) {
var format,
@@ -549,20 +556,14 @@ if the directive is deleted so we don't introduce a memory leak.
updateTime();
});
function scheduleUpdate() {
// save the timeoutId for canceling
timeoutId = $timeout(function() {
updateTime(); // update DOM
scheduleUpdate(); // schedule the next update
}, 1000);
}
element.on('$destroy', function() {
$timeout.cancel(timeoutId);
$interval.cancel(timeoutId);
});
// start the UI update process.
scheduleUpdate();
// start the UI update process; save the timeoutId for canceling
timeoutId = $interval(function() {
updateTime(); // update DOM
}, 1000);
}
return {
@@ -580,7 +581,7 @@ if the directive is deleted so we don't introduce a memory leak.
There are a couple of things to note here.
Just like the `module.controller` API, the function argument in `module.directive` is dependency
injected. Because of this, we can use `$timeout` and `dateFilter` inside our directive's `link`
injected. Because of this, we can use `$interval` and `dateFilter` inside our directive's `link`
function.
We register an event `element.on('$destroy', ...)`. What fires this `$destroy` event?
@@ -717,7 +718,7 @@ own behavior to it.
</file>
<file name="index.html">
<div ng-controller="Ctrl">
<my-dialog ng-hide="dialogIsHidden" on-close="dialogIsHidden = true">
<my-dialog ng-hide="dialogIsHidden" on-close="hideDialog()">
Check out the contents, {{name}}!
</my-dialog>
</div>
+1 -1
View File
@@ -18,7 +18,7 @@ It might be tempting to think of Angular view expressions as JavaScript expressi
not entirely correct, since Angular does not use a JavaScript `eval()` to evaluate expressions.
You can think of Angular expressions as JavaScript expressions with following differences:
* **Attribute Evaluation:** evaluation of all properties are against the scope, doing the
* **Attribute Evaluation:** evaluation of all properties are against the scope doing the
evaluation, unlike in JavaScript where the expressions are evaluated against the global
`window`.
+11 -6
View File
@@ -33,10 +33,10 @@ In addition it provides an {@link api/ng.directive:ngModel.NgModelController API
<script>
function Controller($scope) {
$scope.master= {};
$scope.master = {};
$scope.update = function(user) {
$scope.master= angular.copy(user);
$scope.master = angular.copy(user);
};
$scope.reset = function() {
@@ -115,9 +115,14 @@ This ensures that the user is not distracted with an error until after interacti
A form is an instance of {@link api/ng.directive:form.FormController FormController}.
The form instance can optionally be published into the scope using the `name` attribute.
Similarly, control is an instance of {@link api/ng.directive:ngModel.NgModelController NgModelController}.
The control instance can similarly be published into the form instance using the `name` attribute.
This implies that the internal state of both the form and the control is available for binding in the view using the standard binding primitives.
Similarly, an input control that has the {@link api/ng.directive:ngModel} directive holds an
instance of {@link api/ng.directive:ngModel.NgModelController NgModelController}.
Such a control instance can be published as a property of the form instance using the `name` attribute
on the input control. The name attribute specifies the name of the property on the form instance.
This implies that the internal state of both the form and the control is available for binding in
the view using the standard binding primitives.
This allows us to extend the above example with these features:
@@ -230,7 +235,7 @@ In the following example we create two directives.
<script>
var app = angular.module('form-example1', []);
var INTEGER_REGEXP = /^\-?\d*$/;
var INTEGER_REGEXP = /^\-?\d+$/;
app.directive('integer', function() {
return {
require: 'ngModel',
+1 -1
View File
@@ -43,7 +43,7 @@ http://userguide.icu-project.org/locale ICU } website for more information about
**Supported locales in Angular**
Angular separates number and datetime format rule sets into different files, each file for a
particular locale. You can find a list of currently supported locales {@link
https://github.com/angular/angular.js/tree/master/i18n/locale here}
https://github.com/angular/angular.js/tree/master/src/ngLocale here}
# Providing locale rules to Angular
There are two approaches to providing locale rules to Angular:
+12 -1
View File
@@ -8,6 +8,17 @@ This document describes the Internet Explorer (IE) idiosyncrasies when dealing w
attributes and tags. Read this document if you are planning on deploying your Angular application
on IE v8.0 or earlier.
The project currently supports and will attempt to fix bugs for IE8 and above. The continuous
integration server runs all the tests against IE8. See http://ci.angularjs.org.
IE7 and below are not tested and the project makes no guarantee that Angular will work on it.
A subset of the AngularJS functionality may work. It is up to you to test and decide whether
it works for your particular app.
It is very unlikely that issues specific to IE7 or earlier will be given any time by the core team.
[GitHub](https://github.com/angular/angular.js/issues/4974)
# Short Version
To make your Angular application work on IE please make sure that:
@@ -80,7 +91,7 @@ The **important** parts are:
IE has issues with element tag names which are not standard HTML tag names. These fall into two
categories, and each category has its own fix.
* If the tag name starts with `my:` prefix than it is considered an XML namespace and must
* If the tag name starts with `my:` prefix then it is considered an XML namespace and must
have corresponding namespace declaration on `<html xmlns:my="ignored">`
* If the tag has no `:` but it is not a standard HTML tag, then it must be pre-created using
+6 -46
View File
@@ -7,19 +7,14 @@
Everything you need to know about AngularJS
* {@link guide/introduction What is AngularJS?}
* {@link guide/concepts Conceptual Overview}
## Tutorials
* {@link tutorial/index Official AngularJS Tutorial}
* [10 Reasons Why You Should Use AngularJS](http://www.sitepoint.com/10-reasons-use-angularjs/)
* [Design Principles of AngularJS (video)](https://www.youtube.com/watch?v=HCR7i5F5L8c)
* [Fundamentals in 60 Minutes (video)](http://www.youtube.com/watch?v=i9MHigUZKEM)
* [For folks with jQuery background](http://stackoverflow.com/questions/14994391/how-do-i-think-in-angularjs-if-i-have-a-jquery-background)
## Core Concepts
@@ -29,63 +24,44 @@ Everything you need to know about AngularJS
In Angular applications, you move the job of filling page templates with data from the server to the client. The result is a system better structured for dynamic page updates. Below are the core features you'll use.
* {@link guide/databinding Data binding}
* {@link guide/expression Expressions}
* {@link guide/directive Directives}
* {@link api/ngRoute.$route Views and routes (see the example)}
* {@link guide/filter Filters}
* {@link guide/forms Forms} and [Concepts of AngularJS Forms](http://mrbool.com/the-concepts-of-angularjs-forms/29117)
### Application Structure
* **Blog post: **[When to use directives, controllers or services](http://kirkbushell.me/when-to-use-directives-controllers-or-services-in-angular/)
* **App wiring:** {@link guide/di Dependency injection}
* **Exposing model to templates:** {@link guide/scope Scopes}
* **Communicating with servers:** {@link api/ng.$http $http}, {@link api/ngResource.$resource $resource}
### Other AngularJS Features
* **Animation:** {@link guide/animations Core concepts}, {@link api/ngAnimate ngAnimate API}, and [Animation in AngularJS 1.2](http://www.yearofmoo.com/2013/08/remastered-animation-in-angularjs-1-2.html)
* **Security:** {@link api/ng.$sce Strict Contextual Escaping}, {@link api/ng.directive:ngCsp Content Security Policy}, {@link api/ngSanitize.$sanitize $sanitize}, [video](https://www.youtube.com/watch?v=18ifoT-Id54)
* **Internationalization and Localization:** {@link guide/i18n Angular Guide to i18n and l10n}, {@link api/ng.filter:date date filter}, {@link api/ng.filter:currency currency filter}, [Creating multilingual support](http://www.novanet.no/blog/hallstein-brotan/dates/2013/10/creating-multilingual-support-using-angularjs/)
* **Mobile:** {@link api/ngTouch Touch events}
### Testing
* **Unit testing:** [Using Karma (video)](http://www.youtube.com/watch?v=YG5DEzaQBIc), {@link guide/dev_guide.unit-testing Unit testing}, {@link guide/dev_guide.services.testing_services Testing services}, [Karma in Webstorm](http://blog.jetbrains.com/webstorm/2013/10/running-javascript-tests-with-karma-in-webstorm-7/)
* **Scenario testing:** [Protractor](https://github.com/angular/protractor)
## Specific Topics
* **Login: **[Google example](https://developers.google.com/+/photohunt/python), [Facebook example](http://blog.brunoscopelliti.com/facebook-authentication-in-your-angularjs-web-app), [authentication strategy](http://blog.brunoscopelliti.com/deal-with-users-authentication-in-an-angularjs-web-app), [unix-style authorization](http://frederiknakstad.com/authentication-in-single-page-applications-with-angular-js/)
* **Mobile:** [Angular on Mobile Guide](http://www.ng-newsletter.com/posts/angular-on-mobile.html), [PhoneGap](http://devgirl.org/2013/06/10/quick-start-guide-phonegap-and-angularjs/)
* **Other Languages:** [CoffeeScript](http://www.coffeescriptlove.com/2013/08/angularjs-and-coffeescript-tutorials.html), [Dart](https://github.com/angular/angular.dart.tutorial/wiki)
* **Realtime: **[Socket.io](http://www.creativebloq.com/javascript/angularjs-collaboration-board-socketio-2132885), [OmniBinder](https://github.com/jeffbcross/omnibinder)
* **Visualization:** [SVG](http://gaslight.co/blog/angular-backed-svgs), [D3.js](http://www.ng-newsletter.com/posts/d3-on-angular.html)
## Tools
* **Debugging:** [Batarang](https://chrome.google.com/webstore/detail/angularjs-batarang/ighdmehidhipcmcojjgiloacoafjmpfk?hl=en)
* **Testing:** [Karma](http://karma-runner.github.io), [Protractor](https://github.com/angular/protractor)
* **Editor support:** [Webstorm](http://plugins.jetbrains.com/plugin/6971) (and [video](http://www.youtube.com/watch?v=LJOyrSh1kDU)), [Sublime Text](https://github.com/angular-ui/AngularJS-sublime-package), [Visual Studio](http://madskristensen.net/post/angularjs-intellisense-in-visual-studio-2012)
* **Workflow:** [Yeoman.io](https://github.com/yeoman/generator-angular) and [Angular Yeoman Tutorial](http://www.sitepoint.com/kickstart-your-angularjs-development-with-yeoman-grunt-and-bower/)
## Complementary Libraries
@@ -93,37 +69,26 @@ In Angular applications, you move the job of filling page templates with data fr
This is a short list of libraries with specific support and documentation for working with Angular. You can find a full list of all known Angular external libraries at [ngmodules.org](http://ngmodules.org/).
* **Internationalization:** [angular-translate](http://pascalprecht.github.io/angular-translate/), [angular-gettext](http://angular-gettext.rocketeer.be/)
* **RESTful services:** [Restangular](https://github.com/mgonto/restangular)
* **SQL and NoSQL backends:** [BreezeJS](http://www.breezejs.com/), [AngularFire](http://angularfire.com/)
* **UI Widgets: **[KendoUI](http://kendo-labs.github.io/angular-kendo/#/), [UI Bootstrap](http://angular-ui.github.io/bootstrap/), [Wijmo](http://wijmo.com/tag/angularjs-2/)
## Deployment
### General
### General
* **Javascript minification: **[Background](http://thegreenpizza.github.io/2013/05/25/building-minification-safe-angular.js-applications/), [ngmin automation tool](http://www.thinkster.io/pick/XlWneEZCqY/angularjs-ngmin)
* **Tracking:** [Angularyitcs (Google Analytics)](http://ngmodules.org/modules/angularytics), [Logging Client-Side Errors](http://www.bennadel.com/blog/2542-Logging-Client-Side-Errors-With-AngularJS-And-Stacktrace-js.htm)
* **SEO:** [By hand](http://www.yearofmoo.com/2012/11/angularjs-and-seo.html), [prerender.io](http://prerender.io/), [Brombone](http://www.brombone.com/), [SEO.js](http://getseojs.com/), [SEO4Ajax](http://www.seo4ajax.com/)
### Server-Specific
* **Django:** [Tutorial](http://blog.mourafiq.com/post/55034504632/end-to-end-web-app-with-django-rest-framework), [Integrating AngularJS with Django](http://django-angular.readthedocs.org/en/latest/integration.html)
* **FireBase:** [AngularFire](http://angularfire.com/), [Realtime Apps with AngularJS and FireBase (video)](http://www.youtube.com/watch?v=C7ZI7z7qnHU)
* **Google Cloud Platform: **[with Cloud Endpoints](https://cloud.google.com/resources/articles/angularjs-cloud-endpoints-recipe-for-building-modern-web-applications), [with Go](https://github.com/GoogleCloudPlatform/appengine-angular-gotodos)
* **Hood.ie:** [60 Minutes to Awesome](http://www.roberthorvick.com/2013/06/30/todomvc-angularjs-hood-ie-60-minutes-to-awesome/)
* **MEAN Stack: **[Blog post](http://blog.mongodb.org/post/49262866911/the-mean-stack-mongodb-expressjs-angularjs-and), [Setup](http://thecodebarbarian.wordpress.com/2013/07/22/introduction-to-the-mean-stack-part-one-setting-up-your-tools/), [GDL Video](https://developers.google.com/live/shows/913996610)
* **Rails: **[Tutorial](http://coderberry.me/blog/2013/04/22/angularjs-on-rails-4-part-1/), [AngularJS with Rails4](https://shellycloud.com/blog/2013/10/how-to-integrate-angularjs-with-rails-4), [angularjs-rails](https://github.com/hiravgandhi/angularjs-rails)
* **PHP: **[Building a RESTful web service](http://blog.brunoscopelliti.com/building-a-restful-web-service-with-angularjs-and-php-more-power-with-resource), [End to End with Laravel 4 (video)](http://www.youtube.com/watch?v=hqAyiqUs93c)
## Learning Resources
@@ -137,18 +102,18 @@ This is a short list of libraries with specific support and documentation for wo
* [ng-book: The Complete Book on AngularJS](http://ng-book.com/) by Ari Lerner
###Videos:
* [egghead.io](http://egghead.io/),
* [egghead.io](http://egghead.io/)
* [Angular on YouTube](http://youtube.com/angularjs)
###Courses
* **Free on-line:**
### Courses
* **Free online:**
[thinkster.io](http://thinkster.io),
[CodeAcademy](http://www.codecademy.com/courses/javascript-advanced-en-2hJ3J/0/1)
* **Paid on-line:**
* **Paid online:**
[Pluralsite (3 courses)](http://www.pluralsight.com/training/Courses/Find?highlight=true&searchTerm=angularjs),
[Tuts+](https://tutsplus.com/course/easier-js-apps-with-angular/),
[lynda.com](http://www.lynda.com/AngularJS-tutorials/Up-Running-AngularJS/133318-2.html)
* **Paid on-site:**
* **Paid onsite:**
[angularbootcamp.com](http://angularbootcamp.com/)
## Getting Help
@@ -156,19 +121,14 @@ This is a short list of libraries with specific support and documentation for wo
The recipe for getting help on your unique issue is to create an example that could work (even if it doesn't) in a shareable example on [Plunker](http://plnkr.co/), [JSFiddle](http://jsfiddle.net/), or similar site and then post to one of the following:
* [Stackoverflow.com](http://stackoverflow.com/search?q=angularjs)
* [AngularJS mailing list](https://groups.google.com/forum/#!forum/angular)
* [AngularJS IRC channel](http://webchat.freenode.net/?channels=angularjs&uio=d4)
## Social Channels
* **Daily updates:** [Google+](https://plus.google.com/u/0/+AngularJS) or [Twitter](https://twitter.com/angularjs)
* **Weekly newsletter:** [ng-newsletter](http://www.ng-newsletter.com/)
* **Meetups: **[meetup.com](http://www.meetup.com/find/?keywords=angularJS&radius=Infinity&userFreeform=San+Francisco%2C+CA&mcId=z94108&mcName=San+Francisco%2C+CA&sort=member_count&eventFilter=mysugg)
* **Official news and releases: **[AngularJS Blog](http://blog.angularjs.org/)
## Contributing to AngularJS
+11 -7
View File
@@ -3,7 +3,7 @@
@description
AngularJS version 1.2 introduces several breaking changes that will may require changes to your
AngularJS version 1.2 introduces several breaking changes that may require changes to your
application's source code.
Although we try to avoid breaking changes, there are some cases where it is unavoidable.
@@ -35,7 +35,7 @@ below should still apply, but you may want to consult the
<li>{@link guide/migration#resource-methods-return-the-promise Resource methods return the promise}</li>
<li>{@link guide/migration#resource-promises-are-resolved-with-the-resource-instance Resource promises are resolved with the resource instance}</li>
<li>{@link guide/migration#$locationsearch-supports-multiple-keys $location.search supports multiple keys}</li>
<li>{@link guide/migration#nghtmlbindunsafe-has-been-removed-and-replaced-by-nghtmlbind ngHtmlBindUnsafe has been removed and replaced by ngHtmlBind}</li>
<li>{@link guide/migration#ngbindhtmlunsafe-has-been-removed-and-replaced-by-ngbindhtml ngBindHtmlUnsafe has been removed and replaced by ngBindHtml}</li>
<li>{@link guide/migration#form-names-that-are-expressions-are-evaluated Form names that are expressions are evaluated}</li>
<li>{@link guide/migration#hasownproperty-disallowed-as-an-input-name hasOwnProperty disallowed as an input name}</li>
<li>{@link guide/migration#directives-order-of-postlink-functions-reversed Directives: Order of postLink functions reversed}</li>
@@ -45,7 +45,7 @@ below should still apply, but you may want to consult the
<li>{@link guide/migration#urls-are-now-sanitized-against-a-whitelist URLs are now sanitized against a whitelist}</li>
<li>{@link guide/migration#isolate-scope-only-exposed-to-directives-with-property Isolate scope only exposed to directives with <code>scope</code> property}</li>
<li>{@link guide/migration#change-to-interpolation-priority Change to interpolation priority}</li>
<li>{@link guide/migration#underscore-prefixed/suffixed-prorperties-are-non-bindable Underscore-prefixed/suffixed prorperties are non-bindable}</li>
<li>{@link guide/migration#underscore-prefixed/suffixed-properties-are-non-bindable Underscore-prefixed/suffixed properties are non-bindable}</li>
<li>{@link guide/migration#you-cannot-bind-to-select[multiple] You cannot bind to select[multiple]}</li>
<li>{@link guide/migration#uncommon-region-specific-local-files-were-removed-from-i18n Uncommon region-specific local files were removed from i18n}</li>
</ul>
@@ -376,11 +376,11 @@ passing it to `$location`.
See [80739409](https://github.com/angular/angular.js/commit/807394095b991357225a03d5fed81fea5c9a1abe).
## ngHtmlBindUnsafe has been removed and replaced by ngHtmlBind
## ngBindHtmlUnsafe has been removed and replaced by ngBindHtml
`ngHtmlBind` which has been moved from `ngSanitize` module to the core `ng` module.
`ngBindHtml` which has been moved from `ngSanitize` module to the core `ng` module.
`ngBindHtml` provides `ngHtmlBindUnsafe` like
`ngBindHtml` provides `ngBindHtmlUnsafe` like
behavior (evaluate an expression and innerHTML the result into the DOM) when bound to the result
of `$sce.trustAsHtml(string)`. When bound to a plain string, the string is sanitized via
`$sanitize` before being innerHTML'd. If the `$sanitize` service isn't available (`ngSanitize`
@@ -588,7 +588,11 @@ See [79223eae](https://github.com/angular/angular.js/commit/79223eae502283889334
[#4528](https://github.com/angular/angular.js/issues/4528), and
[#4649](https://github.com/angular/angular.js/issues/4649)
## Underscore-prefixed/suffixed prorperties 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
whose names begin and/or end with an underscore) on the scope chain.
+2 -2
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
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
based on the `clientId` value and a secret stored in browser's local storage:
@@ -228,7 +228,7 @@ myApp.provider('unicornLauncher', function UnicornLauncherProvider() {
// let's assume that the UnicornLauncher constructor was also changed to
// accept and use the useTinfoilShielding argument
return new UnicornLauncher(apiToken, useTinfoilShielding);
}]);
}];
});
```
+11 -5
View File
@@ -18,8 +18,12 @@ watch {@link guide/expression expressions} and propagate events.
propagate any model changes through the system into the view from outside of the "Angular
realm" (controllers, services, Angular event handlers).
- Scopes can be nested to isolate application components while providing access to shared model
properties. A scope (prototypically) inherits properties from its parent scope.
- Scopes can be nested to limit access to the properties of application components while providing
access to shared model properties. Nested scopes are either "child scopes" or "isolate scopes".
A "child scope" (prototypically) inherits properties from its parent scope. An "isolate scope"
does not. See {@link
guide/directive#creating-custom-directives_demo_isolating-the-scope-of-a-directive isolated
scopes} for more information.
- Scopes provide context against which {@link guide/expression expressions} are evaluated. For
example `{{username}}` expression is meaningless, unless it is evaluated against a specific
@@ -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`
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
@@ -259,8 +263,8 @@ the `$digest` phase. This delay is desirable, since it coalesces multiple model
For mutations to be properly observed, you should make them only within the {@link
api/ng.$rootScope.Scope#methods_$apply scope.$apply()}. (Angular APIs do this
implicitly, so no extra `$apply` call is needed when doing synchronous work in controllers,
or asynchronous work with {@link api/ng.$http $http} or {@link
api/ng.$timeout $timeout} services.
or asynchronous work with {@link api/ng.$http $http}, {@link api/ng.$timeout $timeout}
or {@link api/ng.$interval $interval} services.
4. **Mutation observation**
@@ -306,6 +310,8 @@ api/ng.directive:ngController ng-controller} and {@link
api/ng.directive:ngRepeat ng-repeat}, create new child scopes
and attach the child scope to the corresponding DOM element. You can retrieve a scope for any DOM
element by using an `angular.element(aDomElement).scope()` method call.
See the {@link guide/directive#creating-custom-directives_demo_isolating-the-scope-of-a-directive
directives guide} for more information about isolate scopes.
### Controllers and Scopes
+3 -1
View File
@@ -23,7 +23,7 @@ for how to contribute your own code to AngularJS.
Before you can build AngularJS, you must install and configure the following dependencies on your
machine:
* {@link http://git-scm.com/ Git}: The {@link http://help.github.com/mac-git-installation Github Guide to
* {@link http://git-scm.com/ Git}: The {@link https://help.github.com/articles/set-up-git Github Guide to
Installing Git} is a good source of information.
* {@link http://nodejs.org Node.js}: We use Node to generate the documentation, run a
@@ -46,6 +46,8 @@ and included in your {@link http://docs.oracle.com/javase/tutorial/essential/env
npm install -g bower
```
**Note:** You may need to use sudo (for OSX, *nix, BSD etc) or run your command shell as Administrator (for Windows) to install Grunt &amp;
Bower globally.
## Forking Angular on Github
+1 -1
View File
@@ -67,7 +67,7 @@ illustration we typically build snappy apps with hundreds or thousands of active
### How big is the angular.js file that I need to include?
The size of the file is < 29KB compressed and minified.
The size of the file is < 36KB compressed and minified.
### Can I use the open-source Closure Library with Angular?
+1 -1
View File
@@ -85,7 +85,7 @@ to run <code>scripts/web-server.js</code>, a simple bundled http server.</p></l
<div class="tab-pane well" id="git-win" title="Git on Windows">
<ol>
<li><p>You will need Node.js and Karma to run unit tests, so please verify that you have
<a href="http://nodejs.org/">Node.js</a> v0.8 or better installed
<a href="http://nodejs.org/">Node.js</a> v0.10 or better installed
and that the <code>node</code> executable is on your <code>PATH</code> by running the following
command in a terminal window:</p>
<pre>node --version</pre>
+3 -3
View File
@@ -26,7 +26,7 @@ angular-seed, and run the application in the browser.
<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>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>
</li>
<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>
<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>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>
</li>
<li><b>For other http servers:</b>
@@ -179,7 +179,7 @@ For the purposes of this tutorial, we modified the angular-seed with the followi
* Removed the example app
* Added phone images to `app/img/phones/`
* Added phone data files (JSON) to `app/phones/`
* Added [Bootstrap](http://twitter.github.com/bootstrap/) files to `app/css/` and `app/img/`
* Added [Bootstrap](http://getbootstrap.com) files to `app/css/` and `app/img/`
+7 -3
View File
@@ -180,11 +180,15 @@ is available to be injected.
Angular developers prefer the syntax of Jasmine's Behavior-driven Development (BDD) framework when
writing tests. Although Angular does not require you to use Jasmine, we wrote all of the tests in
this tutorial in Jasmine. You can learn about Jasmine on the {@link
http://pivotal.github.com/jasmine/ Jasmine home page} and on the {@link
https://github.com/pivotal/jasmine/wiki Jasmine wiki}.
http://pivotal.github.com/jasmine/ Jasmine home page} and at the {@link
http://pivotal.github.io/jasmine/ Jasmine docs}.
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
`./scripts/test.sh` to start the Karma server (the config file necessary to start the server
+3 -3
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
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.
You can do this by issuing `npm install karma-ng-scenario` into your terminal.
Note: You must ensure you've installed the karma-ng-scenario framework plugin prior to running the
`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
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
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.
+7 -6
View File
@@ -88,7 +88,7 @@ phonecatApp.controller('PhoneListCtrl', function ($scope) {
record. This property is used to order phones by age.
* We added a line to the controller that sets the default value of `orderProp` to `age`. If we had
not set the default value here, the model would stay uninitialized until our user would pick an
not set the default value here, the model would stay uninitialized until our user picks 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
@@ -112,11 +112,12 @@ describe('PhoneCat controllers', function() {
describe('PhoneListCtrl', function(){
var scope, ctrl;
beforeEach(function() {
scope = {},
ctrl = new PhoneListCtrl(scope);
});
beforeEach(module('phonecatApp'));
beforeEach(inject(function($controller) {
scope = {};
ctrl = $controller('PhoneListCtrl', {$scope:scope});
}));
it('should create "phones" model with 3 phones', function() {
expect(scope.phones.length).toBe(3);
+1 -1
View File
@@ -199,7 +199,7 @@ isolated from the work done in other tests.
* We created a new scope for our controller by calling `$rootScope.$new()`
* We called the injected `$controller` function passing the name of the`PhoneListCtrl` controller
* We called the injected `$controller` function passing the name of the `PhoneListCtrl` controller
and the created scope as parameters.
Because our code now uses the `$http` service to fetch the phone list data in our controller, before
+1 -1
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
browser from treating the angular `{{ expression }}` markup literally, and initiating a request to
invalid url `http://localhost:8000/app/{{phone.imageUrl}}`, which it would have done if we had only
specified an attribute binding in a regular `src` attribute (`<img 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.
+2 -2
View File
@@ -258,7 +258,7 @@ to various URLs and verify that the correct view was rendered.
<pre>
...
it('should redirect index.html to index.html#/phones', function() {
browser().navigateTo('../../app/index.html');
browser().navigateTo('app/index.html');
expect(browser().location().url()).toBe('/phones');
});
...
@@ -266,7 +266,7 @@ to various URLs and verify that the correct view was rendered.
describe('Phone detail view', function() {
beforeEach(function() {
browser().navigateTo('../../app/index.html#/phones/nexus-s');
browser().navigateTo('app/index.html#/phones/nexus-s');
});
+1 -1
View File
@@ -120,7 +120,7 @@ Angular's server}.
<button ng-click="hello('Elmo')">Hello</button>
to the `phone-details.html` template.
to the `phone-detail.html` template.
<div style="display: none">
TODO!
+2 -2
View File
@@ -11,7 +11,7 @@ In this step, you will improve the way our app fetches data.
<div doc-tutorial-reset="11"></div>
The last improvement we will make to our app is to define a custom service that represents a {@link
The next improvement we will make to our app is to define a custom service that represents a {@link
http://en.wikipedia.org/wiki/Representational_State_Transfer RESTful} client. Using this client we
can make XHR requests for data in an easier way, without having to deal with the lower-level {@link
api/ng.$http $http} API, HTTP methods and URLs.
@@ -185,7 +185,7 @@ describe('PhoneCat controllers', function() {
xyzPhoneData = function() {
return {
name: 'phone xyz',
images: ['image/url1.png', 'image/url2.png']
images: ['image/url1.png', 'image/url2.png']
}
};
+6 -6
View File
@@ -43,7 +43,7 @@ __`app/index.html`.__
<pre>
...
<!-- 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 -->
<script src="lib/angular/angular-animate.js"></script>
@@ -56,6 +56,10 @@ __`app/index.html`.__
...
</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`).
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`.
@@ -153,7 +157,7 @@ __`app/css/animations.css`__
</pre>
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-move` class is applied when items are moved around in the list.
@@ -383,10 +387,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
`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
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
+2 -2
View File
@@ -34,8 +34,8 @@ describe('ngdoc', function() {
var d1 = new Doc('@name a.b.c').parse();
var d2 = new Doc('@name a.b.ng-c').parse();
var d3 = new Doc('@name some text: more text').parse();
expect(ngdoc.metadata([d1])[0].shortName).toEqual('c');
expect(ngdoc.metadata([d2])[0].shortName).toEqual('ng-c');
expect(ngdoc.metadata([d1])[0].shortName).toEqual('a.b.c');
expect(ngdoc.metadata([d2])[0].shortName).toEqual('a.b.ng-c');
expect(ngdoc.metadata([d3])[0].shortName).toEqual('more text');
});
+1 -1
View File
@@ -20,7 +20,7 @@ describe('Docs Links', function() {
});
it('should have an "view source" button', function() {
spyOn(gruntUtil, 'getVersion').andReturn({cdn: '1.2.299'});
spyOn(gruntUtil, 'getVersion').andReturn({full: '1.2.299'});
expect(doc.html()).
toContain('<a href="http://github.com/angular/angular.js/tree/v1.2.299/test.js#L42" class="view-source btn btn-action"><i class="icon-zoom-in"> </i> View source</a>');
+1 -1
View File
@@ -3,7 +3,7 @@
*/
exports.appCache = appCache;
var fs = require('q-fs');
var fs = require('q-io/fs');
var Q = require('qq');
function identity($) {return $;}
+4 -4
View File
@@ -74,10 +74,10 @@ function writeTheRest(writesFuture) {
var versions = ngdoc.ngVersions();
var currentVersion = ngdoc.ngCurrentVersion();
writesFuture.push(writer.symlink('../../docs/content/notes', 'build/docs/notes', 'dir'));
writesFuture.push(writer.symlinkTemplate('css', 'dir'));
writesFuture.push(writer.symlink('../../docs/img', 'build/docs/img', 'dir'));
writesFuture.push(writer.symlinkTemplate('js', 'dir'));
writesFuture.push(writer.symlink('../../docs/content/notes', 'build/docs/notes', 'directory'));
writesFuture.push(writer.symlinkTemplate('css', 'directory'));
writesFuture.push(writer.symlink('../../docs/img', 'build/docs/img', 'directory'));
writesFuture.push(writer.symlinkTemplate('js', 'directory'));
var manifest = 'manifest="/build/docs/appcache.manifest"';
+1 -1
View File
@@ -7,7 +7,7 @@ exports.collect = collect;
var ngdoc = require('./ngdoc.js'),
Q = require('qq'),
qfs = require('q-fs'),
qfs = require('q-io/fs'),
PATH = require('path');
var NEW_LINE = /\n\r?/;
+25
View File
@@ -144,6 +144,27 @@
.content h4,
.content h5 {
margin-top: 1em;
letter-spacing: -0.06em;
}
.content h2 {
font-size: 36px;
margin-bottom: .5em;
}
.content h3 {
font-size: 24px;
border-top: 1px solid #eee;
padding-top: .5em;
}
.content h4 {
font-size: 16px;
margin-top: 1.5em;
}
.content ul {
margin-top: .5em;
}
ul.parameters > li > p,
@@ -522,6 +543,10 @@ pre ol li {
margin-bottom:30px;
}
.definition-table td {
vertical-align: top;
}
.component-heading {
text-transform:capitalize;
}
+3 -4
View File
@@ -335,9 +335,8 @@
<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 class="alert alert-info">
<a href="http://blog.angularjs.org/2013/11/farewell-disqus.html">Where did Disqus go?</a>
</div>
</div>
</div>
@@ -365,7 +364,7 @@
<footer class="footer">
<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>
Super-powered by Google ©2010-2012
+19 -28
View File
@@ -273,10 +273,10 @@ docsApp.directive.docTutorialNav = function(templateMerge) {
element.addClass('btn-group');
element.addClass('tutorial-nav');
element.append(templateMerge(
'<li class="btn btn-primary"><a href="tutorial/{{prev}}"><i class="icon-step-backward"></i> Previous</a></li>\n' +
'<li class="btn btn-primary"><a href="http://angular.github.com/angular-phonecat/step-{{seq}}/app"><i class="icon-play"></i> Live Demo</a></li>\n' +
'<li class="btn btn-primary"><a href="https://github.com/angular/angular-phonecat/compare/step-{{diffLo}}...step-{{diffHi}}"><i class="icon-search"></i> Code Diff</a></li>\n' +
'<li class="btn btn-primary"><a href="tutorial/{{next}}">Next <i class="icon-step-forward"></i></a></li>', props));
'<a href="tutorial/{{prev}}"><li class="btn btn-primary"><i class="icon-step-backward"></i> Previous</li></a>\n' +
'<a href="http://angular.github.com/angular-phonecat/step-{{seq}}/app"><li class="btn btn-primary"><i class="icon-play"></i> Live Demo</li></a>\n' +
'<a href="https://github.com/angular/angular-phonecat/compare/step-{{diffLo}}...step-{{diffHi}}"><li class="btn btn-primary"><i class="icon-search"></i> Code Diff</li></a>\n' +
'<a href="tutorial/{{next}}"><li class="btn btn-primary">Next <i class="icon-step-forward"></i></li></a>', props));
}
};
};
@@ -372,6 +372,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) {
var urls = {};
@@ -680,7 +695,6 @@ docsApp.controller.DocsController = function($scope, $location, $window, $cookie
var currentPageId = $location.path();
$scope.partialTitle = $scope.currentPage.shortName;
$window._gaq.push(['_trackPageview', currentPageId]);
loadDisqus(currentPageId);
};
/** stores a cookie that is used by apache to decide which manifest ot send */
@@ -892,29 +906,6 @@ docsApp.controller.DocsController = function($scope, $location, $window, $cookie
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('');
}
};
+2 -2
View File
@@ -3,7 +3,7 @@
* for testability
*/
var pathUtils = require('path');
var qfs = require('q-fs');
var qfs = require('q-io/fs');
var Q = require('qq');
var OUTPUT_DIR = pathUtils.join('build','docs');
var TEMPLATES_DIR = pathUtils.join('docs','src','templates');
@@ -76,7 +76,7 @@ function symlink(from, to, type) {
// qfs will normalize the path arguments for us here
return qfs.exists(to).then(function(exists) {
if (!exists) {
return qfs.symbolicLink(to, from, type);
return qfs.symbolicLink(to, from, type || 'file');
}
});
}
+6 -2
View File
@@ -1,9 +1,12 @@
#!/bin/bash
echo "#################################"
echo "#### Jenkins Build ############"
echo "#################################"
# Enable tracing and exit on first failure
set -xe
# Define reasonable set of browsers in case we are running manually from commandline
if [[ -z "$BROWSERS" ]]
then
@@ -25,11 +28,12 @@ rm -f angular.js.size
npm install --color false
grunt ci-checks package --no-color
# DOCS generator unit tests #
grunt test:docgen --no-color
# UNIT TESTS #
grunt test:unit --browsers $BROWSERS --reporters=dots,junit --no-colors --no-color
# END TO END TESTS #
grunt test:e2e --browsers $BROWSERS_E2E --reporters=dots,junit --no-colors --no-color
+3 -1
View File
@@ -20,6 +20,8 @@ module.exports = function(config) {
junitReporter: {
outputFile: 'test_out/e2e.xml',
suite: 'E2E'
}
},
browserNoActivityTimeout: 90000
});
};
+122 -6
View File
@@ -5,14 +5,26 @@ module.exports = function(config, specificOptions) {
logLevel: config.LOG_INFO,
logColors: true,
browsers: ['Chrome'],
browserDisconnectTimeout: 5000,
browserDisconnectTimeout: 10000,
browserDisconnectTolerance: 2,
browserNoActivityTimeout: 20000,
// config for Travis CI
// SauceLabs config for local development.
sauceLabs: {
testName: specificOptions.testName || 'AngularJS',
startConnect: false,
tunnelIdentifier: process.env.TRAVIS_JOB_NUMBER
startConnect: true,
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:
@@ -49,12 +61,77 @@ module.exports = function(config, specificOptions) {
browserName: 'internet explorer',
platform: 'Windows 2012',
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) {
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.
// This speeds up the capturing a bit, as browsers don't even try to use websocket.
config.transports = ['xhr-polling'];
@@ -62,8 +139,47 @@ module.exports = function(config, specificOptions) {
// Debug logging into a file, that we print out at the end of the build.
config.loggers.push({
type: 'file',
filename: process.env.LOGS_DIR + '/' + (specificOptions.logFile || 'karma.log'),
level: config.LOG_DEBUG
filename: process.env.LOGS_DIR + '/' + (specificOptions.logFile || 'karma.log')
});
}
// 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;
};
};
+46
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);
});
+1
View File
@@ -0,0 +1 @@
node ./lib/browser-stack/start-tunnel.js &
+26 -3
View File
@@ -5,6 +5,22 @@ var spawn = require('child_process').spawn;
var version;
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 = {
init: function() {
@@ -20,13 +36,12 @@ module.exports = {
var package = JSON.parse(fs.readFileSync('package.json', 'UTF-8'));
var match = package.version.match(/^([^\-]*)(?:\-(.+))?$/);
var semver = match[1].split('.');
var hash = shell.exec('git rev-parse --short HEAD', {silent: true}).output.replace('\n', '');
var fullVersion = match[1];
if (match[2]) {
fullVersion += '-';
fullVersion += (match[2] == 'snapshot') ? hash : match[2];
fullVersion += (match[2] == 'snapshot') ? getSnapshotSuffix() : match[2];
}
version = {
@@ -39,6 +54,12 @@ module.exports = {
};
return version;
function getSnapshotSuffix() {
var jenkinsBuild = process.env.BUILD_NUMBER || 'local';
var hash = shell.exec('git rev-parse --short HEAD', {silent: true}).output.replace('\n', '');
return 'build.'+jenkinsBuild+'+sha.'+hash;
}
},
@@ -295,5 +316,7 @@ module.exports = {
},
// 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()
};
+2 -2
View File
@@ -36,8 +36,8 @@ ARGS=""
if [ ! -z "$TRAVIS_JOB_NUMBER" ]; then
ARGS="$ARGS --tunnel-identifier $TRAVIS_JOB_NUMBER"
fi
if [ ! -z "$SAUCE_CONNECT_READY_FILE" ]; then
ARGS="$ARGS --readyfile $SAUCE_CONNECT_READY_FILE"
if [ ! -z "$BROWSER_PROVIDER_READY_FILE" ]; then
ARGS="$ARGS --readyfile $BROWSER_PROVIDER_READY_FILE"
fi
+13 -10
View File
@@ -1,8 +1,8 @@
{
"name": "angularjs",
"version": "1.2.1",
"cdnVersion": "1.2.0",
"codename": "underscore-empathy",
"version": "1.2.7",
"cdnVersion": "1.2.6",
"codename": "emoji-clairvoyance",
"repository": {
"type": "git",
"url": "https://github.com/angular/angular.js.git"
@@ -10,34 +10,37 @@
"devDependencies": {
"grunt": "~0.4.1",
"bower": "~1.2.2",
"grunt-bump": "~0.0.13",
"grunt-contrib-clean": "~0.5.0",
"grunt-contrib-compress": "~0.5.2",
"grunt-contrib-connect": "~0.5.0",
"grunt-contrib-copy": "~0.4.1",
"jasmine-node": "~1.11.0",
"q": "~0.9.2",
"q-fs": "~0.1.36",
"q-io": "~1.10.6",
"qq": "~0.3.5",
"shelljs": "~0.2.6",
"karma": "~0.11",
"karma": "0.11.11",
"karma-jasmine": "~0.1.0",
"karma-chrome-launcher": "~0.1.0",
"karma-firefox-launcher": "~0.1.0",
"karma-ng-scenario": "~0.1.0",
"karma-junit-reporter": "git://github.com/karma-runner/karma-junit-reporter#karma-0.11",
"karma-sauce-launcher": "~0.1.1",
"karma-junit-reporter": "~0.2.1",
"karma-sauce-launcher": "~0.2.0",
"karma-script-launcher": "~0.1.0",
"yaml-js": "~0.0.8",
"marked": "0.2.9",
"rewire": "1.1.3",
"grunt-jasmine-node": "~0.1.0",
"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",
"grunt-shell": "~0.4.0",
"semver": "~2.1.0",
"lodash": "~2.1.0"
"lodash": "~2.1.0",
"karma-browserstack-launcher": "git://github.com/karma-runner/karma-browserstack-launcher.git#master",
"browserstacktunnel-wrapper": "~1.1.1"
},
"licenses": [
{
@@ -46,6 +49,6 @@
}
],
"dependencies": {
"grunt-contrib-jshint": "~0.6.4"
"grunt-contrib-jshint": "~0.7.2"
}
}
-34
View File
@@ -1,34 +0,0 @@
#!/usr/bin/env bash
function catch_errors() {
echo "ERROR. That's life."
exit 1
}
trap catch_errors ERR
TMP_FILE='changelog.tmp'
CHANGELOG_FILE='CHANGELOG.md'
echo "Getting current version..."
VERSION=`./version.js --current`
echo "Generating changelog..."
./changelog.js $VERSION $TMP_FILE
cat $CHANGELOG_FILE >> $TMP_FILE
mv -f $TMP_FILE $CHANGELOG_FILE
echo "Updating version..."
./version.js --remove-snapshot
echo "CONFIRM TO COMMIT"
read WHATEVER
echo "Creating commit..."
git commit version.yaml CHANGELOG.md -m "chore(relase): cutting the v$VERSION release"
echo "Creating tag..."
git tag "v$VERSION"
+15
View File
@@ -0,0 +1,15 @@
# Angular Bower Script
Script for updating the Angular bower repos from current local build.
## Instructions
`grunt package`: Build angular locally
```shell
./publish.sh
```
## License
MIT
+88
View File
@@ -0,0 +1,88 @@
#!/bin/bash
echo "#################################"
echo "#### Update bower ###############"
echo "#################################"
# Enable tracing and exit on first failure
set -xe
# Normalize working dir to script dir
cd `dirname $0`
SCRIPT_DIR=`pwd`
TMP_DIR=../../tmp
BUILD_DIR=../../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 \
)
#
# 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
sed -i .tmp -E 's/"(version)":[ ]*".*"/"\1": "'$NEW_VERSION'"/g' bower.json
sed -i .tmp -E 's/"(angular.*)":[ ]*".*"/"\1": "'$NEW_VERSION'"/g' bower.json
# delete tmp files
rm *.tmp
git add -A
echo "-- Committing, tagging and pushing bower-$repo"
git commit -m "v$NEW_VERSION"
git tag v$NEW_VERSION
git push origin master
git push origin v$NEW_VERSION
cd $SCRIPT_DIR
done
+18
View File
@@ -0,0 +1,18 @@
# code.angular.js.org Script
Script for updating code.angularjs.org repo from current local build.
Note: For a snapshot build, this will fetch the data from the ci server
and NOT take the local build!
## Instructions
`grunt package`: Build angular locally
```shell
./publish.sh
```
## License
MIT
+62
View File
@@ -0,0 +1,62 @@
#!/bin/bash
echo "#################################"
echo "## Update code.angular.js.org ###"
echo "#################################"
# Enable tracing and exit on first failure
set -xe
# Normalize working dir to script dir
cd `dirname $0`
TMP_DIR=../../tmp
REPO_DIR=$TMP_DIR/code.angularjs.org
BUILD_DIR=../../build
SCRIPT_DIR=`pwd`
NEW_VERSION=`cat $BUILD_DIR/version.txt`
#
# Snapshot builds are kept in a temp directory in code.angularjs.org
# that is filled by calling a php script there.
#
if [[ "$NEW_VERSION" =~ sha ]] ;then
echo "-- updating snapshot version"
curl -G --data-urlencode "ver=$NEW_VERSION" http://code.angularjs.org/fetchLatestSnapshot.php
exit 0;
fi
#
# clone
#
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 and push
#
echo "-- Committing and pushing code.angularjs.org"
cd $REPO_DIR
git add -A
git commit -m "v$NEW_VERSION"
git push origin master
cd $SCRIPT_DIR
#
# refresh code.angularjs.org from github
#
curl http://code.angularjs.org/gitFetchSite.php
+25
View File
@@ -0,0 +1,25 @@
#!/bin/bash
echo "############################################"
echo "## Increment version and add "-snapshot" ##"
echo "############################################"
if [ "$1" != "patch" -a "$1" != "minor" -a "$1" != "major" ]; then
echo "Please specify the next version type: patch|minor|major"
exit 1
fi
BUMP_TYPE=$1
# Enable tracing and exit on first failure
set -xe
# Normalize working dir to script dir
cd `dirname $0`/../..
echo "-- increment version "
grunt bump:$BUMP_TYPE
NEXT_VERSION=`sed -En 's/.*"version"[ ]*:[ ]*"(.*)".*/\1/p' package.json`
sed -i .tmp -E 's/"version": "(.*)"/"version": "\1-snapshot"/' package.json
echo "-- new version: `grep '"version"' package.json`"
echo "-- commit"
git add package.json
git commit -m "chore(release): start v$NEXT_VERSION"
+20
View File
@@ -0,0 +1,20 @@
#!/bin/bash
echo "############################################"
echo "## Remove "-snapshot" from version ########"
echo "############################################"
# Enable tracing and exit on first failure
set -xe
# Normalize working dir to script dir
cd `dirname $0`/../..
echo "-- old version: `grep '"version"' package.json`"
sed -i .tmp -E 's/"version": "(.*)-snapshot"/"version": "\1"/' package.json
VERSION=`sed -En 's/.*"version"[ ]*:[ ]*"(.*)".*/\1/p' package.json`
echo "-- local version: $VERSION"
echo "-- commit and tag with v$VERSION"
git add package.json
git commit -m "chore(release): cut v$VERSION release"
git tag -m "v$VERSION" v$VERSION
+25
View File
@@ -0,0 +1,25 @@
#!/bin/bash
echo "#################################"
echo "#### Update master ##############"
echo "#################################"
# Enable tracing and exit on first failure
set -xe
cd `dirname $0`/../..
echo "#################################"
echo "#### Jenkins Build ############"
echo "#################################"
./jenkins_build.sh
echo "#################################"
echo "## Update code.angular.js.org ###"
echo "#################################"
./scripts/code.angularjs.org/publish.sh
echo "#################################"
echo "#### Update bower ###############"
echo "#################################"
./scripts/bower/publish.sh
+44
View File
@@ -0,0 +1,44 @@
#!/bin/bash
echo "#################################"
echo "#### Cut release ################"
echo "#################################"
if [ "$1" != "patch" -a "$1" != "minor" -a "$1" != "major" ]; then
echo "Please specify the next version type: patch|minor|major"
exit 1
fi
BUMP_TYPE=$1
# Enable tracing and exit on first failure
set -xe
# Jump onto the master branch and make sure we are using the latest
git checkout -f master
git merge --ff-only origin/master
# Normalize working dir to script dir
cd `dirname $0`/../..
# Bump versions: remove "-snapshot" suffix
./scripts/jenkins/bump-remove-snapshot.sh
# Build
./jenkins_build.sh
# Bump versions: Increment version and add "-snapshot"
./scripts/jenkins/bump-increment.sh $BUMP_TYPE
echo "-- push to Github"
# push the commits to github
git push origin master
# push the release tag
git push origin v`cat build/version.txt`
# Update code.angularjs.org
./scripts/code.angularjs.org/publish.sh
# Update bower
./scripts/bower/publish.sh
+16
View File
@@ -0,0 +1,16 @@
#!/bin/bash
set -e
export SAUCE_ACCESS_KEY=`echo $SAUCE_ACCESS_KEY | rev`
if [ $JOB = "unit" ]; then
grunt ci-checks
grunt test:docgen
grunt test:promises-aplus
grunt test:unit --browsers SL_Chrome,SL_Safari,SL_Firefox,SL_IE_8,SL_IE_9,SL_IE_10,SL_IE_11 --reporters dots
elif [ $JOB = "e2e" ]; then
grunt test:e2e --browsers SL_Chrome --reporters dots
else
echo "Unknown job type. Please set JOB=unit or JOB=e2e."
fi
@@ -2,6 +2,6 @@
# Wait for Connect to be ready before exiting
while [ ! -f $SAUCE_CONNECT_READY_FILE ]; do
while [ ! -f $BROWSER_PROVIDER_READY_FILE ]; do
sleep .5
done
+1 -1
View File
@@ -162,4 +162,4 @@
"nullFormCtrl": false
}
}
}
+62 -44
View File
@@ -80,7 +80,7 @@
-assertArgFn,
-assertNotHasOwnProperty,
-getter,
-getBlockElements
-getBlockElements,
*/
@@ -213,7 +213,9 @@ function forEach(obj, iterator, context) {
if (obj) {
if (isFunction(obj)){
for (key in obj) {
if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {
// Need to check if hasOwnProperty exists,
// as on IE8 the result of querySelectorAll is an object without a hasOwnProperty function
if (key != 'prototype' && key != 'length' && key != 'name' && (!obj.hasOwnProperty || obj.hasOwnProperty(key))) {
iterator.call(context, obj[key], key);
}
}
@@ -393,7 +395,7 @@ function valueFn(value) {return function() {return value;};}
* @param {*} value Reference to check.
* @returns {boolean} True if `value` is undefined.
*/
function isUndefined(value){return typeof value == 'undefined';}
function isUndefined(value){return typeof value === 'undefined';}
/**
@@ -407,7 +409,7 @@ function isUndefined(value){return typeof value == 'undefined';}
* @param {*} value Reference to check.
* @returns {boolean} True if `value` is defined.
*/
function isDefined(value){return typeof value != 'undefined';}
function isDefined(value){return typeof value !== 'undefined';}
/**
@@ -422,7 +424,7 @@ function isDefined(value){return typeof value != 'undefined';}
* @param {*} value Reference to check.
* @returns {boolean} True if `value` is an `Object` but not `null`.
*/
function isObject(value){return value != null && typeof value == 'object';}
function isObject(value){return value != null && typeof value === 'object';}
/**
@@ -436,7 +438,7 @@ function isObject(value){return value != null && typeof value == 'object';}
* @param {*} value Reference to check.
* @returns {boolean} True if `value` is a `String`.
*/
function isString(value){return typeof value == 'string';}
function isString(value){return typeof value === 'string';}
/**
@@ -450,7 +452,7 @@ function isString(value){return typeof value == 'string';}
* @param {*} value Reference to check.
* @returns {boolean} True if `value` is a `Number`.
*/
function isNumber(value){return typeof value == 'number';}
function isNumber(value){return typeof value === 'number';}
/**
@@ -465,7 +467,7 @@ function isNumber(value){return typeof value == 'number';}
* @returns {boolean} True if `value` is a `Date`.
*/
function isDate(value){
return toString.apply(value) == '[object Date]';
return toString.call(value) === '[object Date]';
}
@@ -481,7 +483,7 @@ function isDate(value){
* @returns {boolean} True if `value` is an `Array`.
*/
function isArray(value) {
return toString.apply(value) == '[object Array]';
return toString.call(value) === '[object Array]';
}
@@ -496,7 +498,7 @@ function isArray(value) {
* @param {*} value Reference to check.
* @returns {boolean} True if `value` is a `Function`.
*/
function isFunction(value){return typeof value == 'function';}
function isFunction(value){return typeof value === 'function';}
/**
@@ -507,7 +509,7 @@ function isFunction(value){return typeof value == 'function';}
* @returns {boolean} True if `value` is a `RegExp`.
*/
function isRegExp(value) {
return toString.apply(value) == '[object RegExp]';
return toString.call(value) === '[object RegExp]';
}
@@ -529,12 +531,12 @@ function isScope(obj) {
function isFile(obj) {
return toString.apply(obj) === '[object File]';
return toString.call(obj) === '[object File]';
}
function isBoolean(value) {
return typeof value == 'boolean';
return typeof value === 'boolean';
}
@@ -544,7 +546,7 @@ var trim = (function() {
// TODO: we should move this into IE/ES5 polyfill
if (!String.prototype.trim) {
return function(value) {
return isString(value) ? value.replace(/^\s*/, '').replace(/\s*$/, '') : value;
return isString(value) ? value.replace(/^\s\s*/, '').replace(/\s\s*$/, '') : value;
};
}
return function(value) {
@@ -565,9 +567,9 @@ var trim = (function() {
* @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element).
*/
function isElement(node) {
return node &&
return !!(node &&
(node.nodeName // we are a direct element
|| (node.on && node.find)); // we have an on and find method part of jQuery API
|| (node.on && node.find))); // we have an on and find method part of jQuery API
}
/**
@@ -638,7 +640,7 @@ function includes(array, obj) {
function indexOf(array, obj) {
if (array.indexOf) return array.indexOf(obj);
for ( var i = 0; i < array.length; i++) {
for (var i = 0; i < array.length; i++) {
if (obj === array[i]) return i;
}
return -1;
@@ -768,8 +770,8 @@ function shallowCopy(src, dst) {
for(var key in src) {
// shallowCopy is only ever called by $compile nodeLinkFn, which has control over src
// so we don't need to worry hasOwnProperty here
if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') {
// so we don't need to worry about using our custom hasOwnProperty here
if (src.hasOwnProperty(key) && key.charAt(0) !== '$' && key.charAt(1) !== '$') {
dst[key] = src[key];
}
}
@@ -957,7 +959,9 @@ function fromJson(json) {
function toBoolean(value) {
if (value && value.length !== 0) {
if (typeof value === 'function') {
value = true;
} else if (value && value.length !== 0) {
var v = lowercase("" + value);
value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');
} else {
@@ -974,7 +978,7 @@ function startingTag(element) {
try {
// turns out IE does not let you set .html() on elements which
// are not allowed to have children. So we just ignore it.
element.html('');
element.empty();
} catch(e) {}
// As Per DOM Standards
var TEXT_NODE = 3;
@@ -1102,26 +1106,38 @@ function encodeUriQuery(val, pctEncodeSpaces) {
*
* @description
*
* Use this directive to auto-bootstrap an application. Only
* one ngApp directive can be used per HTML document. The directive
* designates the root of the application and is typically placed
* at the root of the page.
* Use this directive to **auto-bootstrap** an AngularJS application. The `ngApp` directive
* designates the **root element** of the application and is typically placed near the root element
* of the page - e.g. on the `<body>` or `<html>` tags.
*
* The first ngApp found in the document will be auto-bootstrapped. To use multiple applications in
* an HTML document you must manually bootstrap them using {@link angular.bootstrap}.
* Applications cannot be nested.
* Only one AngularJS application can be auto-bootstrapped per HTML document. The first `ngApp`
* found in the document will be used to define the root element to auto-bootstrap as an
* application. To run multiple applications in an HTML document you must manually bootstrap them using
* {@link angular.bootstrap} instead. AngularJS applications cannot be nested within each other.
*
* In the example below if the `ngApp` directive were not placed
* on the `html` element then the document would not be compiled
* and the `{{ 1+2 }}` would not be resolved to `3`.
* You can specify an **AngularJS module** to be used as the root module for the application. This
* module will be loaded into the {@link AUTO.$injector} when the application is bootstrapped and
* should contain the application code needed or have dependencies on other modules that will
* contain the code. See {@link angular.module} for more information.
*
* `ngApp` is the easiest way to bootstrap an application.
* In the example below if the `ngApp` directive were not placed on the `html` element then the
* document would not be compiled, the `AppController` would not be instantiated and the `{{ a+b }}`
* would not be resolved to `3`.
*
<doc:example>
<doc:source>
I can add: 1 + 2 = {{ 1+2 }}
</doc:source>
</doc:example>
* `ngApp` is the easiest, and most common, way to bootstrap an application.
*
<example module="ngAppDemo">
<file name="index.html">
<div ng-controller="ngAppDemoController">
I can add: {{a}} + {{b}} = {{ a+b }}
</file>
<file name="script.js">
angular.module('ngAppDemo', []).controller('ngAppDemoController', function($scope) {
$scope.a = 1;
$scope.b = 2;
});
</file>
</example>
*
*/
function angularInit(element, bootstrap) {
@@ -1318,23 +1334,25 @@ function getter(obj, path, bindFnToScope) {
}
/**
* Return the siblings between `startNode` and `endNode`, inclusive
* @param {Object} object with `startNode` and `endNode` properties
* Return the DOM siblings between the first and last node in the given array.
* @param {Array} array like object
* @returns jQlite object containing the elements
*/
function getBlockElements(block) {
if (block.startNode === block.endNode) {
return jqLite(block.startNode);
function getBlockElements(nodes) {
var startNode = nodes[0],
endNode = nodes[nodes.length - 1];
if (startNode === endNode) {
return jqLite(startNode);
}
var element = block.startNode;
var element = startNode;
var elements = [element];
do {
element = element.nextSibling;
if (!element) break;
elements.push(element);
} while (element !== block.endNode);
} while (element !== endNode);
return jqLite(elements);
}
+9
View File
@@ -28,6 +28,7 @@
ngHideDirective,
ngIfDirective,
ngIncludeDirective,
ngIncludeFillContentDirective,
ngInitDirective,
ngNonBindableDirective,
ngPluralizeDirective,
@@ -65,6 +66,7 @@
$ParseProvider,
$RootScopeProvider,
$QProvider,
$$SanitizeUriProvider,
$SceProvider,
$SceDelegateProvider,
$SnifferProvider,
@@ -136,6 +138,10 @@ function publishExternalAPI(angular){
angularModule('ng', ['ngLocale'], ['$provide',
function ngModule($provide) {
// $$sanitizeUriProvider needs to be before $compileProvider as it is used by it.
$provide.provider({
$$sanitizeUri: $$SanitizeUriProvider
});
$provide.provider('$compile', $CompileProvider).
directive({
a: htmlAnchorDirective,
@@ -176,6 +182,9 @@ function publishExternalAPI(angular){
ngRequired: requiredDirective,
ngValue: ngValueDirective
}).
directive({
ngInclude: ngIncludeFillContentDirective
}).
directive(ngAttributeAliasDirectives).
directive(ngEventDirectives);
$provide.provider({
+1 -1
View File
@@ -1,6 +1,6 @@
/**
* @license AngularJS v"NG_VERSION_FULL"
* (c) 2010-2012 Google, Inc. http://angularjs.org
* (c) 2010-2014 Google, Inc. http://angularjs.org
* License: MIT
*/
(function(window, document, undefined) {
+37 -25
View File
@@ -27,6 +27,28 @@
* $rootScope.$digest();
* });
* </pre>
*
* Sometimes you want to get access to the injector of a currently running Angular app
* from outside Angular. Perhaps, you want to inject and compile some markup after the
* application has been bootstrapped. You can do this using extra `injector()` added
* to JQuery/jqLite elements. See {@link angular.element}.
*
* *This is fairly rare but could be the case if a third party library is injecting the
* markup.*
*
* In the following example a new block of HTML containing a `ng-controller`
* directive is added to the end of the document body by JQuery. We then compile and link
* it into the current AngularJS scope.
*
* <pre>
* var $div = $('<div ng-controller="MyCtrl">{{content.label}}</div>');
* $(document.body).append($div);
*
* angular.element(document).injector().invoke(function($compile) {
* var scope = angular.element($div).scope();
* $compile($div)(scope);
* });
* </pre>
*/
@@ -221,7 +243,7 @@ function annotate(fn) {
* // ...
* }
* // Define function dependencies
* MyController.$inject = ['$scope', '$route'];
* MyController['$inject'] = ['$scope', '$route'];
*
* // Then
* expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);
@@ -463,15 +485,15 @@ function annotate(fn) {
* {@link AUTO.$provide#methods_service $provide.service(class)} that is defined as a CoffeeScript class.
* <pre>
* class Ping
* constructor: (@$http)->
* send: ()=>
* constructor: (@$http) ->
* send: () =>
* @$http.get('/ping')
*
* $provide.service('ping', ['$http', Ping])
* </pre>
* You would then inject and use this service like this:
* <pre>
* someModule.controller 'Ctrl', ['ping', (ping)->
* someModule.controller 'Ctrl', ['ping', (ping) ->
* ping.send()
* ]
* </pre>
@@ -501,11 +523,11 @@ function annotate(fn) {
* @example
* Here are some examples of creating value services.
* <pre>
* $provide.constant('ADMIN_USER', 'admin');
* $provide.value('ADMIN_USER', 'admin');
*
* $provide.constant('RoleLookup', { admin: 0, writer: 1, reader: 2 });
* $provide.value('RoleLookup', { admin: 0, writer: 1, reader: 2 });
*
* $provide.constant('halfOf', function(value) {
* $provide.value('halfOf', function(value) {
* return value / 2;
* });
* </pre>
@@ -718,6 +740,11 @@ function createInjector(modulesToLoad) {
path.unshift(serviceName);
cache[serviceName] = INSTANTIATING;
return cache[serviceName] = factory(serviceName);
} catch (err) {
if (cache[serviceName] === INSTANTIATING) {
delete cache[serviceName];
}
throw err;
} finally {
path.shift();
}
@@ -747,24 +774,9 @@ function createInjector(modulesToLoad) {
fn = fn[length];
}
// Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke
switch (self ? -1 : args.length) {
case 0: return fn();
case 1: return fn(args[0]);
case 2: return fn(args[0], args[1]);
case 3: return fn(args[0], args[1], args[2]);
case 4: return fn(args[0], args[1], args[2], args[3]);
case 5: return fn(args[0], args[1], args[2], args[3], args[4]);
case 6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]);
case 7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
case 8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);
case 9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7],
args[8]);
case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7],
args[8], args[9]);
default: return fn.apply(self, args);
}
// http://jsperf.com/angularjs-invoke-apply-vs-switch
// #5388
return fn.apply(self, args);
}
function instantiate(Type, locals) {
+41 -6
View File
@@ -46,6 +46,7 @@
* - [`contents()`](http://api.jquery.com/contents/)
* - [`css()`](http://api.jquery.com/css/)
* - [`data()`](http://api.jquery.com/data/)
* - [`empty()`](http://api.jquery.com/empty/)
* - [`eq()`](http://api.jquery.com/eq/)
* - [`find()`](http://api.jquery.com/find/) - Limited to lookups by tag name
* - [`hasClass()`](http://api.jquery.com/hasClass/)
@@ -53,6 +54,7 @@
* - [`next()`](http://api.jquery.com/next/) - Does not support selectors
* - [`on()`](http://api.jquery.com/on/) - Does not support namespaces, selectors or eventData
* - [`off()`](http://api.jquery.com/off/) - Does not support namespaces or selectors
* - [`one()`](http://api.jquery.com/one/) - Does not support namespaces or selectors
* - [`parent()`](http://api.jquery.com/parent/) - Does not support selectors
* - [`prepend()`](http://api.jquery.com/prepend/)
* - [`prop()`](http://api.jquery.com/prop/)
@@ -358,6 +360,15 @@ function jqLiteInheritedData(element, name, value) {
}
}
function jqLiteEmpty(element) {
for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {
jqLiteDealoc(childNodes[i]);
}
while (element.firstChild) {
element.removeChild(element.firstChild);
}
}
//////////////////////////////////////////
// Functions which are declared directly.
//////////////////////////////////////////
@@ -552,7 +563,9 @@ forEach({
jqLiteDealoc(childNodes[i]);
}
element.innerHTML = value;
}
},
empty: jqLiteEmpty
}, function(fn, name){
/**
* Properties: writes return selection, reads return first value
@@ -562,11 +575,13 @@ forEach({
// jqLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it
// in a way that survives minification.
if (((fn.length == 2 && (fn !== jqLiteHasClass && fn !== jqLiteController)) ? arg1 : arg2) === undefined) {
// jqLiteEmpty takes no arguments but is a setter.
if (fn !== jqLiteEmpty &&
(((fn.length == 2 && (fn !== jqLiteHasClass && fn !== jqLiteController)) ? arg1 : arg2) === undefined)) {
if (isObject(arg1)) {
// we are a write, but the object properties are the key/values
for(i=0; i < this.length; i++) {
for (i = 0; i < this.length; i++) {
if (fn === jqLiteData) {
// data() takes the whole object in jQuery
fn(this[i], arg1);
@@ -591,7 +606,7 @@ forEach({
}
} else {
// we are a write, so apply to all children
for(i=0; i < this.length; i++) {
for (i = 0; i < this.length; i++) {
fn(this[i], arg1, arg2);
}
// return self for chaining
@@ -631,7 +646,10 @@ function createEventHandler(element, events) {
return event.defaultPrevented || event.returnValue === false;
};
forEach(events[type || event.type], function(fn) {
// Copy event handlers in case event handlers array is modified during execution.
var eventHandlersCopy = shallowCopy(events[type || event.type] || []);
forEach(eventHandlersCopy, function(fn) {
fn.call(element, event);
});
@@ -727,6 +745,19 @@ forEach({
off: jqLiteOff,
one: function(element, type, fn) {
element = jqLite(element);
//add the listener twice so that when it is called
//you can remove the original function and still be
//able to call element.off(ev, fn) normally
element.on(type, function onFn() {
element.off(type, fn);
element.off(type, onFn);
});
element.on(type, fn);
},
replaceWith: function(element, replaceNode) {
var index, parent = element.parentNode;
jqLiteDealoc(element);
@@ -822,7 +853,11 @@ forEach({
},
find: function(element, selector) {
return element.getElementsByTagName(selector);
if (element.getElementsByTagName) {
return element.getElementsByTagName(selector);
} else {
return [];
}
},
clone: jqLiteClone,
+6 -1
View File
@@ -17,7 +17,12 @@ function setupModuleLoader(window) {
return obj[name] || (obj[name] = factory());
}
return ensure(ensure(window, 'angular', Object), 'module', function() {
var angular = ensure(window, 'angular', Object);
// We need to expose `angular.$$minErr` to modules such as `ngResource` that reference it during bootstrap
angular.$$minErr = angular.$$minErr || minErr;
return ensure(angular, 'module', function() {
/** @type {Object.<string, angular.Module>} */
var modules = {};
+1 -1
View File
@@ -1,6 +1,6 @@
/**
* @license AngularJS v"NG_VERSION_FULL"
* (c) 2010-2012 Google, Inc. http://angularjs.org
* (c) 2010-2014 Google, Inc. http://angularjs.org
* License: MIT
*/
'use strict';
+1 -1
View File
@@ -1,6 +1,6 @@
/**
* @license AngularJS v"NG_VERSION_FULL"
* (c) 2010-2012 Google, Inc. http://angularjs.org
* (c) 2010-2014 Google, Inc. http://angularjs.org
* License: MIT
*/
(function(window, angular, undefined) {
+30 -7
View File
@@ -61,6 +61,28 @@ var $AnimateProvider = ['$provide', function($provide) {
$provide.factory(key, factory);
};
/**
* @ngdoc function
* @name ng.$animateProvider#classNameFilter
* @methodOf ng.$animateProvider
*
* @description
* Sets and/or returns the CSS class regular expression that is checked when performing
* an animation. Upon bootstrap the classNameFilter value is not set at all and will
* therefore enable $animate to attempt to perform an animation on any element.
* When setting the classNameFilter value, animations will only be performed on elements
* that successfully match the filter expression. This in turn can boost performance
* for low-powered devices as well as applications containing a lot of structural operations.
* @param {RegExp=} expression The className expression which will be checked against all animations
* @return {RegExp} The current CSS className expression value. If null then there is no expression value
*/
this.classNameFilter = function(expression) {
if(arguments.length === 1) {
this.$$classNameFilter = (expression instanceof RegExp) ? expression : null;
}
return this.$$classNameFilter;
};
this.$get = ['$timeout', function($timeout) {
/**
@@ -99,13 +121,14 @@ var $AnimateProvider = ['$provide', function($provide) {
* inserted into the DOM
*/
enter : function(element, parent, after, done) {
var afterNode = after && after[after.length - 1];
var parentNode = parent && parent[0] || afterNode && afterNode.parentNode;
// IE does not like undefined so we have to pass null.
var afterNextSibling = (afterNode && afterNode.nextSibling) || null;
forEach(element, function(node) {
parentNode.insertBefore(node, afterNextSibling);
});
if (after) {
after.after(element);
} else {
if (!parent || !parent[0]) {
parent = after.parent();
}
parent.append(element);
}
done && $timeout(done, 0, false);
},
+7 -6
View File
@@ -148,8 +148,9 @@ function Browser(window, document, $log, $sniffer) {
* @param {boolean=} replace Should new url replace current history record ?
*/
self.url = function(url, replace) {
// Android Browser BFCache causes location reference to become stale.
// Android Browser BFCache causes location, history reference to become stale.
if (location !== window.location) location = window.location;
if (history !== window.history) history = window.history;
// setter
if (url) {
@@ -201,7 +202,7 @@ function Browser(window, document, $log, $sniffer) {
* @description
* Register callback function that will be called, when url changes.
*
* It's only called when the url is changed by outside of angular:
* It's only called when the url is changed from outside of angular:
* - user types different url into address bar
* - user clicks on history (forward/back) button
* - user clicks on a link
@@ -243,7 +244,7 @@ function Browser(window, document, $log, $sniffer) {
/**
* @name ng.$browser#baseHref
* @methodOf ng.$browser
*
*
* @description
* Returns current <base href>
* (always relative - without domain)
@@ -252,7 +253,7 @@ function Browser(window, document, $log, $sniffer) {
*/
self.baseHref = function() {
var href = baseElement.attr('href');
return href ? href.replace(/^https?\:\/\/[^\/]*/, '') : '';
return href ? href.replace(/^(https?\:)?\/\/[^\/]*/, '') : '';
};
//////////////////////////////////////////////////////////////
@@ -274,13 +275,13 @@ function Browser(window, document, $log, $sniffer) {
* It is not meant to be used directly, use the $cookie service instead.
*
* The return values vary depending on the arguments that the method was called with as follows:
*
*
* - cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify
* it
* - cookies(name, value) -> set name to value, if value is undefined delete the cookie
* - cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that
* way)
*
*
* @returns {Object} Hash of all cookies (if called without any parameter)
*/
self.cookies = function(name, value) {
+141 -117
View File
@@ -24,7 +24,7 @@
* @function
*
* @description
* Compiles a piece of HTML string or DOM into a template and produces a template function, which
* Compiles an HTML string or DOM into a template and produces a template function, which
* can then be used to link {@link ng.$rootScope.Scope `scope`} and the template together.
*
* The compilation is a process of walking the DOM tree and matching DOM elements to
@@ -192,7 +192,7 @@
* * (no prefix) - Locate the required controller on the current element. Throw an error if not found.
* * `?` - Attempt to locate the required controller or pass `null` to the `link` fn if not found.
* * `^` - Locate the required controller by searching the element's parents. Throw an error if not found.
* * `?^` - Attempt to locate the required controller by searching the element's parentsor pass `null` to the
* * `?^` - Attempt to locate the required controller by searching the element's parents or pass `null` to the
* `link` fn if not found.
*
*
@@ -283,7 +283,7 @@
* </div>
*
* <div class="alert alert-error">
* **Note:** The `transclude` function that is passed to the compile function is deperecated, as it
* **Note:** The `transclude` function that is passed to the compile function is deprecated, as it
* e.g. does not know about the right outer scope. Please use the transclude function that is passed
* to the link function instead.
* </div>
@@ -469,14 +469,14 @@
* example would not point to the clone, but rather to the original template that was cloned. In
* this case, you can access the clone via the cloneAttachFn:
* <pre>
* var templateHTML = angular.element('<p>{{total}}</p>'),
* var templateElement = angular.element('<p>{{total}}</p>'),
* scope = ....;
*
* var clonedElement = $compile(templateHTML)(scope, function(clonedElement, scope) {
* var clonedElement = $compile(templateElement)(scope, function(clonedElement, scope) {
* //attach the clone to DOM document at the right place
* });
*
* //now we have reference to the cloned DOM via `clone`
* //now we have reference to the cloned DOM via `clonedElement`
* </pre>
*
*
@@ -493,14 +493,12 @@ var $compileMinErr = minErr('$compile');
*
* @description
*/
$CompileProvider.$inject = ['$provide'];
function $CompileProvider($provide) {
$CompileProvider.$inject = ['$provide', '$$sanitizeUriProvider'];
function $CompileProvider($provide, $$sanitizeUriProvider) {
var hasDirectives = {},
Suffix = 'Directive',
COMMENT_DIRECTIVE_REGEXP = /^\s*directive\:\s*([\d\w\-_]+)\s+(.*)$/,
CLASS_DIRECTIVE_REGEXP = /(([\d\w\-_]+)(?:\:([^;]+))?;?)/,
aHrefSanitizationWhitelist = /^\s*(https?|ftp|mailto|tel|file):/,
imgSrcSanitizationWhitelist = /^\s*(https?|ftp|file):|data:image\//;
CLASS_DIRECTIVE_REGEXP = /(([\d\w\-_]+)(?:\:([^;]+))?;?)/;
// Ref: http://developers.whatwg.org/webappapis.html#event-handler-idl-attributes
// The assumption is that future DOM event attribute names will begin with
@@ -584,10 +582,11 @@ function $CompileProvider($provide) {
*/
this.aHrefSanitizationWhitelist = function(regexp) {
if (isDefined(regexp)) {
aHrefSanitizationWhitelist = regexp;
$$sanitizeUriProvider.aHrefSanitizationWhitelist(regexp);
return this;
} else {
return $$sanitizeUriProvider.aHrefSanitizationWhitelist();
}
return aHrefSanitizationWhitelist;
};
@@ -614,18 +613,18 @@ function $CompileProvider($provide) {
*/
this.imgSrcSanitizationWhitelist = function(regexp) {
if (isDefined(regexp)) {
imgSrcSanitizationWhitelist = regexp;
$$sanitizeUriProvider.imgSrcSanitizationWhitelist(regexp);
return this;
} else {
return $$sanitizeUriProvider.imgSrcSanitizationWhitelist();
}
return imgSrcSanitizationWhitelist;
};
this.$get = [
'$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse',
'$controller', '$rootScope', '$document', '$sce', '$animate',
'$controller', '$rootScope', '$document', '$sce', '$animate', '$$sanitizeUri',
function($injector, $interpolate, $exceptionHandler, $http, $templateCache, $parse,
$controller, $rootScope, $document, $sce, $animate) {
$controller, $rootScope, $document, $sce, $animate, $$sanitizeUri) {
var Attributes = function(element, attr) {
this.$$element = element;
@@ -672,6 +671,24 @@ function $CompileProvider($provide) {
}
},
/**
* @ngdoc function
* @name ng.$compile.directive.Attributes#$updateClass
* @methodOf ng.$compile.directive.Attributes
* @function
*
* @description
* Adds and removes the appropriate CSS class values to the element based on the difference
* between the new and old CSS class values (specified as newClasses and oldClasses).
*
* @param {string} newClasses The current CSS className value
* @param {string} oldClasses The former CSS className value
*/
$updateClass : function(newClasses, oldClasses) {
this.$removeClass(tokenDifference(oldClasses, newClasses));
this.$addClass(tokenDifference(newClasses, oldClasses));
},
/**
* Set a normalized attribute on the element in a way such that all directives
* can share the attribute. This function properly handles boolean attributes.
@@ -682,59 +699,44 @@ function $CompileProvider($provide) {
* @param {string=} attrName Optional none normalized name. Defaults to key.
*/
$set: function(key, value, writeAttr, attrName) {
//special case for class attribute addition + removal
//so that class changes can tap into the animation
//hooks provided by the $animate service
if(key == 'class') {
value = value || '';
var current = this.$$element.attr('class') || '';
this.$removeClass(tokenDifference(current, value).join(' '));
this.$addClass(tokenDifference(value, current).join(' '));
// TODO: decide whether or not to throw an error if "class"
//is set through this function since it may cause $updateClass to
//become unstable.
var booleanKey = getBooleanAttrName(this.$$element[0], key),
normalizedVal,
nodeName;
if (booleanKey) {
this.$$element.prop(key, value);
attrName = booleanKey;
}
this[key] = value;
// translate normalized key to actual key
if (attrName) {
this.$attr[key] = attrName;
} else {
var booleanKey = getBooleanAttrName(this.$$element[0], key),
normalizedVal,
nodeName;
if (booleanKey) {
this.$$element.prop(key, value);
attrName = booleanKey;
attrName = this.$attr[key];
if (!attrName) {
this.$attr[key] = attrName = snake_case(key, '-');
}
}
this[key] = value;
nodeName = nodeName_(this.$$element);
// translate normalized key to actual key
if (attrName) {
this.$attr[key] = attrName;
// sanitize a[href] and img[src] values
if ((nodeName === 'A' && key === 'href') ||
(nodeName === 'IMG' && key === 'src')) {
this[key] = value = $$sanitizeUri(value, key === 'src');
}
if (writeAttr !== false) {
if (value === null || value === undefined) {
this.$$element.removeAttr(attrName);
} else {
attrName = this.$attr[key];
if (!attrName) {
this.$attr[key] = attrName = snake_case(key, '-');
}
}
nodeName = nodeName_(this.$$element);
// sanitize a[href] and img[src] values
if ((nodeName === 'A' && key === 'href') ||
(nodeName === 'IMG' && key === 'src')) {
// NOTE: urlResolve() doesn't support IE < 8 so we don't sanitize for that case.
if (!msie || msie >= 8 ) {
normalizedVal = urlResolve(value).href;
if (normalizedVal !== '') {
if ((key === 'href' && !normalizedVal.match(aHrefSanitizationWhitelist)) ||
(key === 'src' && !normalizedVal.match(imgSrcSanitizationWhitelist))) {
this[key] = value = 'unsafe:' + normalizedVal;
}
}
}
}
if (writeAttr !== false) {
if (value === null || value === undefined) {
this.$$element.removeAttr(attrName);
} else {
this.$$element.attr(attrName, value);
}
this.$$element.attr(attrName, value);
}
}
@@ -747,22 +749,6 @@ function $CompileProvider($provide) {
$exceptionHandler(e);
}
});
function tokenDifference(str1, str2) {
var values = [],
tokens1 = str1.split(/\s+/),
tokens2 = str2.split(/\s+/);
outer:
for(var i=0;i<tokens1.length;i++) {
var token = tokens1[i];
for(var j=0;j<tokens2.length;j++) {
if(token == tokens2[j]) continue outer;
}
values.push(token);
}
return values;
}
},
@@ -832,6 +818,7 @@ function $CompileProvider($provide) {
var compositeLinkFn =
compileNodes($compileNodes, transcludeFn, $compileNodes,
maxPriority, ignoreDirective, previousCompileContext);
safeAddClass($compileNodes, 'ng-scope');
return function publicLinkFn(scope, cloneConnectFn, transcludeControllers){
assertArg(scope, 'scope');
// important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart
@@ -846,12 +833,13 @@ function $CompileProvider($provide) {
// Attach scope only to non-text nodes.
for(var i = 0, ii = $linkNode.length; i<ii; i++) {
var node = $linkNode[i];
if (node.nodeType == 1 /* element */ || node.nodeType == 9 /* document */) {
var node = $linkNode[i],
nodeType = node.nodeType;
if (nodeType === 1 /* element */ || nodeType === 9 /* document */) {
$linkNode.eq(i).data('$scope', scope);
}
}
safeAddClass($linkNode, 'ng-scope');
if (cloneConnectFn) cloneConnectFn($linkNode, scope);
if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode);
return $linkNode;
@@ -879,15 +867,15 @@ function $CompileProvider($provide) {
* @param {DOMElement=} $rootElement If the nodeList is the root of the compilation tree then
* the rootElement must be set the jqLite collection of the compile root. This is
* needed so that the jqLite collection items can be replaced with widgets.
* @param {number=} max directive priority
* @param {number=} maxPriority Max directive priority.
* @returns {?function} A composite linking function of all of the matched directives or null.
*/
function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority, ignoreDirective,
previousCompileContext) {
var linkFns = [],
nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;
attrs, directives, nodeLinkFn, childNodes, childLinkFn, linkFnFound;
for(var i = 0; i < nodeList.length; i++) {
for (var i = 0; i < nodeList.length; i++) {
attrs = new Attributes();
// we must always refer to nodeList[i] since the nodes can be replaced underneath us.
@@ -899,16 +887,19 @@ function $CompileProvider($provide) {
null, [], [], previousCompileContext)
: null;
if (nodeLinkFn && nodeLinkFn.scope) {
safeAddClass(jqLite(nodeList[i]), 'ng-scope');
}
childLinkFn = (nodeLinkFn && nodeLinkFn.terminal ||
!nodeList[i].childNodes ||
!nodeList[i].childNodes.length)
!(childNodes = nodeList[i].childNodes) ||
!childNodes.length)
? null
: compileNodes(nodeList[i].childNodes,
: compileNodes(childNodes,
nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);
linkFns.push(nodeLinkFn);
linkFns.push(childLinkFn);
linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);
linkFns.push(nodeLinkFn, childLinkFn);
linkFnFound = linkFnFound || nodeLinkFn || childLinkFn;
//use the previous context only for the first element in the virtual group
previousCompileContext = null;
}
@@ -920,9 +911,10 @@ function $CompileProvider($provide) {
var nodeLinkFn, childLinkFn, node, $node, childScope, childTranscludeFn, i, ii, n;
// copy nodeList so that linking doesn't break due to live list updates.
var stableNodeList = [];
for (i = 0, ii = nodeList.length; i < ii; i++) {
stableNodeList.push(nodeList[i]);
var nodeListLength = nodeList.length,
stableNodeList = new Array(nodeListLength);
for (i = 0; i < nodeListLength; i++) {
stableNodeList[i] = nodeList[i];
}
for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {
@@ -935,7 +927,6 @@ function $CompileProvider($provide) {
if (nodeLinkFn.scope) {
childScope = scope.$new();
$node.data('$scope', childScope);
safeAddClass($node, 'ng-scope');
} else {
childScope = scope;
}
@@ -945,7 +936,7 @@ function $CompileProvider($provide) {
createBoundTranscludeFn(scope, childTranscludeFn || transcludeFn)
);
} else {
nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);
nodeLinkFn(childLinkFn, childScope, node, $rootElement, boundTranscludeFn);
}
} else if (childLinkFn) {
childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);
@@ -1018,9 +1009,7 @@ function $CompileProvider($provide) {
nName = directiveNormalize(name.toLowerCase());
attrsMap[nName] = name;
attrs[nName] = value = trim((msie && name == 'href')
? decodeURIComponent(node.getAttribute(name, 2))
: attr.value);
attrs[nName] = value = trim(attr.value);
if (getBooleanAttrName(node, nName)) {
attrs[nName] = true; // presence means true
}
@@ -1233,7 +1222,7 @@ function $CompileProvider($provide) {
});
} else {
$template = jqLite(jqLiteClone(compileNode)).contents();
$compileNode.html(''); // clear contents
$compileNode.empty(); // clear contents
childTranscludeFn = compile($template, transcludeFn);
}
}
@@ -1414,7 +1403,7 @@ function $CompileProvider($provide) {
optional = (match[2] == '?'),
mode = match[1], // @, =, or &
lastValue,
parentGet, parentSet;
parentGet, parentSet, compare;
isolateScope.$$isolateBindings[scopeName] = mode + attrName;
@@ -1437,6 +1426,11 @@ function $CompileProvider($provide) {
return;
}
parentGet = $parse(attrs[attrName]);
if (parentGet.literal) {
compare = equals;
} else {
compare = function(a,b) { return a === b; };
}
parentSet = parentGet.assign || function() {
// reset the change, or we will throw this exception on every $digest
lastValue = isolateScope[scopeName] = parentGet(scope);
@@ -1447,19 +1441,18 @@ function $CompileProvider($provide) {
lastValue = isolateScope[scopeName] = parentGet(scope);
isolateScope.$watch(function parentValueWatch() {
var parentValue = parentGet(scope);
if (parentValue !== isolateScope[scopeName]) {
if (!compare(parentValue, isolateScope[scopeName])) {
// we are out of sync and need to copy
if (parentValue !== lastValue) {
if (!compare(parentValue, lastValue)) {
// parent changed and it has precedence
lastValue = isolateScope[scopeName] = parentValue;
isolateScope[scopeName] = parentValue;
} else {
// if the parent can be assigned then do so
parentSet(scope, parentValue = lastValue = isolateScope[scopeName]);
parentSet(scope, parentValue = isolateScope[scopeName]);
}
}
return parentValue;
});
return lastValue = parentValue;
}, null, parentGet.literal);
break;
case '&':
@@ -1661,7 +1654,7 @@ function $CompileProvider($provide) {
? origAsyncDirective.templateUrl($compileNode, tAttrs)
: origAsyncDirective.templateUrl;
$compileNode.html('');
$compileNode.empty();
$http.get($sce.getTrustedResourceUrl(templateUrl), {cache: $templateCache}).
success(function(content) {
@@ -1784,10 +1777,15 @@ function $CompileProvider($provide) {
function getTrustedContext(node, attrNormalizedName) {
if (attrNormalizedName == "srcdoc") {
return $sce.HTML;
}
var tag = nodeName_(node);
// maction[xlink:href] can source SVG. It's not limited to <maction>.
if (attrNormalizedName == "xlinkHref" ||
(nodeName_(node) != "IMG" && (attrNormalizedName == "src" ||
attrNormalizedName == "ngSrc"))) {
(tag == "FORM" && attrNormalizedName == "action") ||
(tag != "IMG" && (attrNormalizedName == "src" ||
attrNormalizedName == "ngSrc"))) {
return $sce.RESOURCE_URL;
}
}
@@ -1832,9 +1830,19 @@ function $CompileProvider($provide) {
attr[name] = interpolateFn(scope);
($$observers[name] || ($$observers[name] = [])).$$inter = true;
(attr.$$observers && attr.$$observers[name].$$scope || scope).
$watch(interpolateFn, function interpolateFnWatchAction(value) {
attr.$set(name, value);
});
$watch(interpolateFn, function interpolateFnWatchAction(newValue, oldValue) {
//special case for class attribute addition + removal
//so that class changes can tap into the animation
//hooks provided by the $animate service. Be sure to
//skip animations when the first digest occurs (when
//both the new and the old values are the same) since
//the CSS classes are the non-interpolated values
if(name === 'class' && newValue != oldValue) {
attr.$updateClass(newValue, oldValue);
} else {
attr.$set(name, newValue);
}
});
}
};
}
@@ -1974,3 +1982,19 @@ function directiveLinkingFn(
/* Element */ rootElement,
/* function(Function) */ boundTranscludeFn
){}
function tokenDifference(str1, str2) {
var values = '',
tokens1 = str1.split(/\s+/),
tokens2 = str2.split(/\s+/);
outer:
for(var i = 0; i < tokens1.length; i++) {
var token = tokens1[i];
for(var j = 0; j < tokens2.length; j++) {
if(token == tokens2[j]) continue outer;
}
values += (values.length > 0 ? ' ' : '') + token;
}
return values;
}
+10 -8
View File
@@ -32,13 +32,15 @@ var htmlAnchorDirective = valueFn({
element.append(document.createComment('IE fix'));
}
return function(scope, element) {
element.on('click', function(event){
// if we have no href url, then don't navigate anywhere.
if (!element.attr('href')) {
event.preventDefault();
}
});
};
if (!attr.href && !attr.name) {
return function(scope, element) {
element.on('click', function(event){
// if we have no href url, then don't navigate anywhere.
if (!element.attr('href')) {
event.preventDefault();
}
});
};
}
}
});
+29 -6
View File
@@ -4,6 +4,7 @@
* @ngdoc directive
* @name ng.directive:ngHref
* @restrict A
* @priority 99
*
* @description
* Using Angular markup like `{{hash}}` in an href attribute will
@@ -87,6 +88,7 @@
* @ngdoc directive
* @name ng.directive:ngSrc
* @restrict A
* @priority 99
*
* @description
* Using Angular markup like `{{hash}}` in a `src` attribute doesn't
@@ -112,6 +114,7 @@
* @ngdoc directive
* @name ng.directive:ngSrcset
* @restrict A
* @priority 99
*
* @description
* Using Angular markup like `{{hash}}` in a `srcset` attribute doesn't
@@ -137,6 +140,7 @@
* @ngdoc directive
* @name ng.directive:ngDisabled
* @restrict A
* @priority 100
*
* @description
*
@@ -149,8 +153,11 @@
*
* The HTML specification does not require browsers to preserve the values of boolean attributes
* such as disabled. (Their presence means true and their absence means false.)
* This prevents the Angular compiler from retrieving the binding expression.
* If we put an Angular interpolation expression into such an attribute then the
* binding information would be lost when the browser removes the attribute.
* The `ngDisabled` directive solves this problem for the `disabled` attribute.
* This complementary directive is not removed by the browser and so provides
* a permanent reliable place to store the binding information.
*
* @example
<doc:example>
@@ -177,12 +184,16 @@
* @ngdoc directive
* @name ng.directive:ngChecked
* @restrict A
* @priority 100
*
* @description
* The HTML specification does not require browsers to preserve the values of boolean attributes
* such as checked. (Their presence means true and their absence means false.)
* This prevents the Angular compiler from retrieving the binding expression.
* If we put an Angular interpolation expression into such an attribute then the
* binding information would be lost when the browser removes the attribute.
* The `ngChecked` directive solves this problem for the `checked` attribute.
* This complementary directive is not removed by the browser and so provides
* a permanent reliable place to store the binding information.
* @example
<doc:example>
<doc:source>
@@ -208,12 +219,16 @@
* @ngdoc directive
* @name ng.directive:ngReadonly
* @restrict A
* @priority 100
*
* @description
* The HTML specification does not require browsers to preserve the values of boolean attributes
* such as readonly. (Their presence means true and their absence means false.)
* This prevents the Angular compiler from retrieving the binding expression.
* If we put an Angular interpolation expression into such an attribute then the
* binding information would be lost when the browser removes the attribute.
* The `ngReadonly` directive solves this problem for the `readonly` attribute.
* This complementary directive is not removed by the browser and so provides
* a permanent reliable place to store the binding information.
* @example
<doc:example>
<doc:source>
@@ -239,12 +254,17 @@
* @ngdoc directive
* @name ng.directive:ngSelected
* @restrict A
* @priority 100
*
* @description
* The HTML specification does not require browsers to preserve the values of boolean attributes
* such as selected. (Their presence means true and their absence means false.)
* This prevents the Angular compiler from retrieving the binding expression.
* If we put an Angular interpolation expression into such an attribute then the
* binding information would be lost when the browser removes the attribute.
* The `ngSelected` directive solves this problem for the `selected` atttribute.
* This complementary directive is not removed by the browser and so provides
* a permanent reliable place to store the binding information.
*
* @example
<doc:example>
<doc:source>
@@ -272,13 +292,16 @@
* @ngdoc directive
* @name ng.directive:ngOpen
* @restrict A
* @priority 100
*
* @description
* The HTML specification does not require browsers to preserve the values of boolean attributes
* such as open. (Their presence means true and their absence means false.)
* This prevents the Angular compiler from retrieving the binding expression.
* If we put an Angular interpolation expression into such an attribute then the
* binding information would be lost when the browser removes the attribute.
* The `ngOpen` directive solves this problem for the `open` attribute.
*
* This complementary directive is not removed by the browser and so provides
* a permanent reliable place to store the binding information.
* @example
<doc:example>
<doc:source>
+15 -2
View File
@@ -21,9 +21,22 @@ var nullFormCtrl = {
* @property {Object} $error Is an object hash, containing references to all invalid controls or
* forms, where:
*
* - keys are validation tokens (error names) — such as `required`, `url` or `email`,
* - values are arrays of controls or forms that are invalid with given error.
* - keys are validation tokens (error names),
* - values are arrays of controls or forms that are invalid for given error name.
*
*
* Built-in validation tokens:
*
* - `email`
* - `max`
* - `maxlength`
* - `min`
* - `minlength`
* - `number`
* - `pattern`
* - `required`
* - `url`
*
* @description
* `FormController` keeps track of all its controls and nested forms as well as state of them,
* such as being valid/invalid or dirty/pristine.
+27 -40
View File
@@ -392,8 +392,23 @@ var inputType = {
function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
// In composition mode, users are still inputing intermediate text buffer,
// hold the listener until composition is done.
// More about composition events: https://developer.mozilla.org/en-US/docs/Web/API/CompositionEvent
if (!$sniffer.android) {
var composing = false;
element.on('compositionstart', function(data) {
composing = true;
});
element.on('compositionend', function() {
composing = false;
});
}
var listener = function() {
if (composing) return;
var value = element.val();
// By default we will trim the value
@@ -404,9 +419,13 @@ function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
}
if (ctrl.$viewValue !== value) {
scope.$apply(function() {
if (scope.$$phase) {
ctrl.$setViewValue(value);
});
} else {
scope.$apply(function() {
ctrl.$setViewValue(value);
});
}
}
};
@@ -436,15 +455,15 @@ function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
deferListener();
});
// if user paste into input using mouse, we need "change" event to catch it
element.on('change', listener);
// if user modifies input value using context menu in IE, we need "paste" and "cut" events to catch it
if ($sniffer.hasEvent('paste')) {
element.on('paste cut', deferListener);
}
}
// if user paste into input using mouse on older browser
// or form autocomplete on newer browser, we need "change" event to catch it
element.on('change', listener);
ctrl.$render = function() {
element.val(ctrl.$isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue);
@@ -938,39 +957,6 @@ var VALID_CLASS = 'ng-valid',
</file>
* </example>
*
* ## Isolated Scope Pitfall
*
* Note that if you have a directive with an isolated scope, you cannot require `ngModel`
* since the model value will be looked up on the isolated scope rather than the outer scope.
* When the directive updates the model value, calling `ngModel.$setViewValue()` the property
* on the outer scope will not be updated. However you can get around this by using $parent.
*
* Here is an example of this situation. You'll notice that the first div is not updating the input.
* However the second div can update the input properly.
*
* <example module="badIsolatedDirective">
<file name="script.js">
angular.module('badIsolatedDirective', []).directive('isolate', function() {
return {
require: 'ngModel',
scope: { },
template: '<input ng-model="innerModel">',
link: function(scope, element, attrs, ngModel) {
scope.$watch('innerModel', function(value) {
console.log(value);
ngModel.$setViewValue(value);
});
}
};
});
</file>
<file name="index.html">
<input ng-model="someModel"/>
<div isolate ng-model="someModel"></div>
<div isolate ng-model="$parent.someModel"></div>
</file>
* </example>
*
*
*/
var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse',
@@ -1117,7 +1103,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
* It will update the $viewValue, then pass this value through each of the functions in `$parsers`,
* which includes any validators. The value that comes out of this `$parsers` pipeline, be applied to
* `$modelValue` and the **expression** specified in the `ng-model` attribute.
*
*
* Lastly, all the registered change listeners, in the `$viewChangeListeners` list, are called.
*
* Note that calling this function does not trigger a `$digest`.
@@ -1174,6 +1160,8 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
ctrl.$render();
}
}
return value;
});
}];
@@ -1450,7 +1438,6 @@ var CONSTANT_VALUE_REGEXP = /^(true|false|\d+)$/;
id="{{name}}"
name="favorite">
</label>
</span>
<div>You chose {{my.favorite}}</div>
</form>
</doc:source>
+9 -17
View File
@@ -20,11 +20,10 @@ function classDirective(name, selector) {
// jshint bitwise: false
var mod = $index & 1;
if (mod !== old$index & 1) {
if (mod === selector) {
addClass(scope.$eval(attr[name]));
} else {
removeClass(scope.$eval(attr[name]));
}
var classes = flattenClasses(scope.$eval(attr[name]));
mod === selector ?
attr.$addClass(classes) :
attr.$removeClass(classes);
}
});
}
@@ -32,24 +31,17 @@ function classDirective(name, selector) {
function ngClassWatchAction(newVal) {
if (selector === true || scope.$index % 2 === selector) {
if (oldVal && !equals(newVal,oldVal)) {
removeClass(oldVal);
var newClasses = flattenClasses(newVal || '');
if(!oldVal) {
attr.$addClass(newClasses);
} else if(!equals(newVal,oldVal)) {
attr.$updateClass(newClasses, flattenClasses(oldVal));
}
addClass(newVal);
}
oldVal = copy(newVal);
}
function removeClass(classVal) {
attr.$removeClass(flattenClasses(classVal));
}
function addClass(classVal) {
attr.$addClass(flattenClasses(classVal));
}
function flattenClasses(classVal) {
if(isArray(classVal)) {
return classVal.join(' ');
+1 -1
View File
@@ -35,7 +35,7 @@
*
* Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they
* cannot match the `[ng\:cloak]` selector. To work around this limitation, you must add the css
* class `ngCloak` in addition to the `ngCloak` directive as shown in the example below.
* class `ng-cloak` in addition to the `ngCloak` directive as shown in the example below.
*
* @element ANY
*
+2 -1
View File
@@ -167,6 +167,7 @@
var ngControllerDirective = [function() {
return {
scope: true,
controller: '@'
controller: '@',
priority: 500
};
}];
+92 -13
View File
@@ -69,7 +69,14 @@ forEach(
* a dblclick. (The Event object is available as `$event`)
*
* @example
* See {@link ng.directive:ngClick ngClick}
<doc:example>
<doc:source>
<button ng-dblclick="count = count + 1" ng-init="count=0">
Increment (on double click)
</button>
count: {{count}}
</doc:source>
</doc:example>
*/
@@ -85,7 +92,14 @@ forEach(
* mousedown. (Event object is available as `$event`)
*
* @example
* See {@link ng.directive:ngClick ngClick}
<doc:example>
<doc:source>
<button ng-mousedown="count = count + 1" ng-init="count=0">
Increment (on mouse down)
</button>
count: {{count}}
</doc:source>
</doc:example>
*/
@@ -101,7 +115,14 @@ forEach(
* mouseup. (Event object is available as `$event`)
*
* @example
* See {@link ng.directive:ngClick ngClick}
<doc:example>
<doc:source>
<button ng-mouseup="count = count + 1" ng-init="count=0">
Increment (on mouse up)
</button>
count: {{count}}
</doc:source>
</doc:example>
*/
/**
@@ -116,7 +137,14 @@ forEach(
* mouseover. (Event object is available as `$event`)
*
* @example
* See {@link ng.directive:ngClick ngClick}
<doc:example>
<doc:source>
<button ng-mouseover="count = count + 1" ng-init="count=0">
Increment (when mouse is over)
</button>
count: {{count}}
</doc:source>
</doc:example>
*/
@@ -132,7 +160,14 @@ forEach(
* mouseenter. (Event object is available as `$event`)
*
* @example
* See {@link ng.directive:ngClick ngClick}
<doc:example>
<doc:source>
<button ng-mouseenter="count = count + 1" ng-init="count=0">
Increment (when mouse enters)
</button>
count: {{count}}
</doc:source>
</doc:example>
*/
@@ -148,7 +183,14 @@ forEach(
* mouseleave. (Event object is available as `$event`)
*
* @example
* See {@link ng.directive:ngClick ngClick}
<doc:example>
<doc:source>
<button ng-mouseleave="count = count + 1" ng-init="count=0">
Increment (when mouse leaves)
</button>
count: {{count}}
</doc:source>
</doc:example>
*/
@@ -164,7 +206,14 @@ forEach(
* mousemove. (Event object is available as `$event`)
*
* @example
* See {@link ng.directive:ngClick ngClick}
<doc:example>
<doc:source>
<button ng-mousemove="count = count + 1" ng-init="count=0">
Increment (when mouse moves)
</button>
count: {{count}}
</doc:source>
</doc:example>
*/
@@ -180,7 +229,12 @@ forEach(
* keydown. (Event object is available as `$event` and can be interrogated for keyCode, altKey, etc.)
*
* @example
* See {@link ng.directive:ngClick ngClick}
<doc:example>
<doc:source>
<input ng-keydown="count = count + 1" ng-init="count=0">
key down count: {{count}}
</doc:source>
</doc:example>
*/
@@ -196,7 +250,12 @@ forEach(
* keyup. (Event object is available as `$event` and can be interrogated for keyCode, altKey, etc.)
*
* @example
* See {@link ng.directive:ngClick ngClick}
<doc:example>
<doc:source>
<input ng-keyup="count = count + 1" ng-init="count=0">
key up count: {{count}}
</doc:source>
</doc:example>
*/
@@ -212,7 +271,12 @@ forEach(
* keypress. (Event object is available as `$event` and can be interrogated for keyCode, altKey, etc.)
*
* @example
* See {@link ng.directive:ngClick ngClick}
<doc:example>
<doc:source>
<input ng-keypress="count = count + 1" ng-init="count=0">
key press count: {{count}}
</doc:source>
</doc:example>
*/
@@ -311,7 +375,12 @@ forEach(
* copy. (Event object is available as `$event`)
*
* @example
* See {@link ng.directive:ngClick ngClick}
<doc:example>
<doc:source>
<input ng-copy="copied=true" ng-init="copied=false; value='copy me'" ng-model="value">
copied: {{copied}}
</doc:source>
</doc:example>
*/
/**
@@ -326,7 +395,12 @@ forEach(
* cut. (Event object is available as `$event`)
*
* @example
* See {@link ng.directive:ngClick ngClick}
<doc:example>
<doc:source>
<input ng-cut="cut=true" ng-init="cut=false; value='cut me'" ng-model="value">
cut: {{cut}}
</doc:source>
</doc:example>
*/
/**
@@ -341,5 +415,10 @@ forEach(
* paste. (Event object is available as `$event`)
*
* @example
* See {@link ng.directive:ngClick ngClick}
<doc:example>
<doc:source>
<input ng-paste="paste=true" ng-init="paste=false" placeholder='paste here'>
pasted: {{paste}}
</doc:source>
</doc:example>
*/
+6 -6
View File
@@ -59,9 +59,6 @@
padding:10px;
}
/&#42;
The transition styles can also be placed on the CSS base class above
&#42;/
.animate-if.ng-enter, .animate-if.ng-leave {
-webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
@@ -94,9 +91,12 @@ var ngIfDirective = ['$animate', function($animate) {
if (!childScope) {
childScope = $scope.$new();
$transclude(childScope, function (clone) {
clone[clone.length++] = document.createComment(' end ngIf: ' + $attr.ngIf + ' ');
// Note: We only need the first/last node of the cloned nodes.
// However, we need to keep the reference to the jqlite wrapper as it might be changed later
// by a directive with templateUrl when it's template arrives.
block = {
startNode: clone[0],
endNode: clone[clone.length++] = document.createComment(' end ngIf: ' + $attr.ngIf + ' ')
clone: clone
};
$animate.enter(clone, $element.parent(), $element);
});
@@ -109,7 +109,7 @@ var ngIfDirective = ['$animate', function($animate) {
}
if (block) {
$animate.leave(getBlockElements(block));
$animate.leave(getBlockElements(block.clone));
block = null;
}
}
+37 -12
View File
@@ -147,13 +147,14 @@
* @description
* Emitted every time the ngInclude content is reloaded.
*/
var ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile', '$animate', '$sce',
function($http, $templateCache, $anchorScroll, $compile, $animate, $sce) {
var ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$animate', '$sce',
function($http, $templateCache, $anchorScroll, $animate, $sce) {
return {
restrict: 'ECA',
priority: 400,
terminal: true,
transclude: 'element',
controller: angular.noop,
compile: function(element, attr) {
var srcExp = attr.ngInclude || attr.src,
onloadExp = attr.onload || '',
@@ -187,28 +188,52 @@ var ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile'
$http.get(src, {cache: $templateCache}).success(function(response) {
if (thisChangeId !== changeCounter) return;
var newScope = scope.$new();
ctrl.template = response;
$transclude(newScope, function(clone) {
// Note: This will also link all children of ng-include that were contained in the original
// html. If that content contains controllers, ... they could pollute/change the scope.
// However, using ng-include on an element with additional content does not make sense...
// Note: We can't remove them in the cloneAttchFn of $transclude as that
// function is called before linking the content, which would apply child
// directives to non existing elements.
var clone = $transclude(newScope, function(clone) {
cleanupLastIncludeContent();
currentScope = newScope;
currentElement = clone;
currentElement.html(response);
$animate.enter(currentElement, null, $element, afterAnimation);
$compile(currentElement.contents())(currentScope);
currentScope.$emit('$includeContentLoaded');
scope.$eval(onloadExp);
$animate.enter(clone, null, $element, afterAnimation);
});
currentScope = newScope;
currentElement = clone;
currentScope.$emit('$includeContentLoaded');
scope.$eval(onloadExp);
}).error(function() {
if (thisChangeId === changeCounter) cleanupLastIncludeContent();
});
scope.$emit('$includeContentRequested');
} else {
cleanupLastIncludeContent();
ctrl.template = null;
}
});
};
}
};
}];
// This directive is called during the $transclude call of the first `ngInclude` directive.
// It will replace and compile the content of the element with the loaded template.
// We need this directive so that the element content is already filled when
// the link function of another directive on the same element as ngInclude
// is called.
var ngIncludeFillContentDirective = ['$compile',
function($compile) {
return {
restrict: 'ECA',
priority: -400,
require: 'ngInclude',
link: function(scope, $element, $attr, ctrl) {
$element.html(ctrl.template);
$compile($element.contents())(scope);
}
};
}];
+4 -1
View File
@@ -10,12 +10,14 @@
* current scope.
*
* <div class="alert alert-error">
* The only appropriate use of `ngInit` for aliasing special properties of
* The only appropriate use of `ngInit` is for aliasing special properties of
* {@link api/ng.directive:ngRepeat `ngRepeat`}, as seen in the demo below. Besides this case, you
* should use {@link guide/controller controllers} rather than `ngInit`
* to initialize values on a scope.
* </div>
*
* @priority 450
*
* @element ANY
* @param {expression} ngInit {@link guide/expression Expression} to eval.
*
@@ -47,6 +49,7 @@
</doc:example>
*/
var ngInitDirective = ngDirective({
priority: 450,
compile: function() {
return {
pre: function(scope, element, attrs) {
+1 -1
View File
@@ -50,7 +50,7 @@
* other numbers, for example 12, so that instead of showing "12 people are viewing", you can
* show "a dozen people are viewing".
*
* You can use a set of closed braces(`{}`) as a placeholder for the number that you want substituted
* You can use a set of closed braces (`{}`) as a placeholder for the number that you want substituted
* into pluralized strings. In the previous example, Angular will replace `{}` with
* <span ng-non-bindable>`{{personCount}}`</span>. The closed braces `{}` is a placeholder
* for <span ng-non-bindable>{{numberExpression}}</span>.
+23 -13
View File
@@ -99,7 +99,7 @@
* For example: `item in items track by $id(item)`. A built in `$id()` function can be used to assign a unique
* `$$hashKey` property to each item in the array. This property is then used as a key to associated DOM elements
* with the corresponding item in the array by identity. Moving the same object in array would move the DOM
* element in the same way ian the DOM.
* element in the same way in the DOM.
*
* For example: `item in items track by item.id` is a typical pattern when the items come from the database. In this
* case the object identity does not matter. Two objects are considered equivalent as long as their `id`
@@ -203,7 +203,7 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
$$tlb: true,
link: function($scope, $element, $attr, ctrl, $transclude){
var expression = $attr.ngRepeat;
var match = expression.match(/^\s*(.+)\s+in\s+(.*?)\s*(\s+track\s+by\s+(.+)\s*)?$/),
var match = expression.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/),
trackByExp, trackByExpGetter, trackByIdExpFn, trackByIdArrayFn, trackByIdObjFn,
lhs, rhs, valueIdentifier, keyIdentifier,
hashFnLocals = {$id: hashKey};
@@ -215,7 +215,7 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
lhs = match[1];
rhs = match[2];
trackByExp = match[4];
trackByExp = match[3];
if (trackByExp) {
trackByExpGetter = $parse(trackByExp);
@@ -301,7 +301,7 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
} else if (nextBlockMap.hasOwnProperty(trackById)) {
// restore lastBlockMap
forEach(nextBlockOrder, function(block) {
if (block && block.startNode) lastBlockMap[block.id] = block;
if (block && block.scope) lastBlockMap[block.id] = block;
});
// This is a duplicate and we need to throw an error
throw ngRepeatMinErr('dupes', "Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys. Repeater: {0}, Duplicate key: {1}",
@@ -318,7 +318,7 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
// lastBlockMap is our own object so we don't need to use special hasOwnPropertyFn
if (lastBlockMap.hasOwnProperty(key)) {
block = lastBlockMap[key];
elementsToRemove = getBlockElements(block);
elementsToRemove = getBlockElements(block.clone);
$animate.leave(elementsToRemove);
forEach(elementsToRemove, function(element) { element[NG_REMOVED] = true; });
block.scope.$destroy();
@@ -330,9 +330,9 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
key = (collection === collectionKeys) ? index : collectionKeys[index];
value = collection[key];
block = nextBlockOrder[index];
if (nextBlockOrder[index - 1]) previousNode = nextBlockOrder[index - 1].endNode;
if (nextBlockOrder[index - 1]) previousNode = getBlockEnd(nextBlockOrder[index - 1]);
if (block.startNode) {
if (block.scope) {
// if we have already seen this object, then we need to reuse the
// associated scope/element
childScope = block.scope;
@@ -342,11 +342,11 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
nextNode = nextNode.nextSibling;
} while(nextNode && nextNode[NG_REMOVED]);
if (block.startNode != nextNode) {
if (getBlockStart(block) != nextNode) {
// existing item which got moved
$animate.move(getBlockElements(block), null, jqLite(previousNode));
$animate.move(getBlockElements(block.clone), null, jqLite(previousNode));
}
previousNode = block.endNode;
previousNode = getBlockEnd(block);
} else {
// new item which we don't know about
childScope = $scope.$new();
@@ -362,14 +362,16 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
childScope.$odd = !(childScope.$even = (index&1) === 0);
// jshint bitwise: true
if (!block.startNode) {
if (!block.scope) {
$transclude(childScope, function(clone) {
clone[clone.length++] = document.createComment(' end ngRepeat: ' + expression + ' ');
$animate.enter(clone, null, jqLite(previousNode));
previousNode = clone;
block.scope = childScope;
block.startNode = previousNode && previousNode.endNode ? previousNode.endNode : clone[0];
block.endNode = clone[clone.length - 1];
// Note: We only need the first/last node of the cloned nodes.
// However, we need to keep the reference to the jqlite wrapper as it might be changed later
// by a directive with templateUrl when it's template arrives.
block.clone = clone;
nextBlockMap[block.id] = block;
});
}
@@ -378,5 +380,13 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
});
}
};
function getBlockStart(block) {
return block.clone[0];
}
function getBlockEnd(block) {
return block.clone[block.clone.length - 1];
}
}];

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