Compare commits

..

299 Commits

Author SHA1 Message Date
Igor Minar 5745734991 chore(release): cut 1.1.2 tofu-animation release 2013-01-23 10:54:35 -08:00
Igor Minar 0551aa95f0 docs(changelog): release notes for 1.1.2 and 1.0.4 2013-01-22 22:58:55 -08:00
Igor Minar b62327ec2d docs(ngOpen): fix typo in api docs 2013-01-22 22:58:55 -08:00
Igor Minar 07a58dd766 chore(changelog.js): improve the changelog script 2013-01-22 22:49:00 -08:00
Igor Minar ffe5e01584 revert: fix($resource): Route constructor, updated RegExp
This reverts commit 06ed8ef012.

The reverted commit causes regressions. See comments in the PR:
https://github.com/angular/angular.js/pull/1402#issuecomment-12575399
2013-01-22 16:32:02 -08:00
Igor Minar 3c2e1c5e4d fix(angular.equals): relax the comparison for undefined properties
in 5ae63fd3 the comparison was made consistent but strict, so that

angular.equals({}, {foo: undefined}) // always returns false

this turns out to cause issues for data that is being roundtripped via network
and serialized via JSON because JSON.stringify serializes {foo: undefined} as {}.

Since angular.equals() behaved like this before the 5ae63fd3 in 50% of the cases,
changing the behavior in this way should not introduce any significant issues.

Closes #1648
2013-01-22 07:35:21 -08:00
Igor Minar cdf7781878 chore(Rakefile): skip build parallelization on Travis
Due to a infrastructure change on Travis starting JVMs in forked
processes doesn't currently work. Since we don't really care that
much about the build speed on Travis, I'm going to disable it there.

Related issue: https://github.com/travis-ci/travis-ci/issues/845
2013-01-21 07:50:16 -08:00
sergiopantoja 7e8d3c1736 docs(jqLite): fix typo 2013-01-20 18:39:21 +01:00
Will Moore d30845a757 docs(contribute): adding npm install to step-by-step
npm install is listed in the dependencies section of the contribute guide but
is missing from the step-by-step. This adds it as step 4.
2013-01-18 21:33:10 -08:00
Fredrik Bonander 06ed8ef012 fix($resource): Route constructor, updated RegExp
Update RegExp to allow urlParams with out leading slash (/).
- Will allow reoucese to be loaded from a relative path

Example:
var R = $resource(':path');
R.get({ path : 'data.json' });

Example usage:
Load resources in applications not using webserver, ie local webapp in on a tablet.
2013-01-18 21:28:15 -08:00
Pedro Del Gallego 2f437e8978 feat(scenario): add mouseover method to the ngScenario dsl 2013-01-18 21:24:57 -08:00
Luis Ramón López faf02f0c4d feat(route): Allow using functions as template params in 'when' 2013-01-18 21:20:49 -08:00
David Chang b8bd4d5460 feat(directive): added ng-open boolean directive
Closes# 1797 add ng-open attribute
2013-01-18 21:16:16 -08:00
pavelgj b2f46251ac fix(ngResource): correct leading slash removal.
Fixed an issues with ngResource param substitution where it was incorrectly removing leading slash when param was followed by a non-slash character.
Ex:
'/:foo/:bar.baz/:aux'

params = {
  foo: 'aaa',
  bar: undefined,
  aux: undefined
}

The above params were incorrectly producing '/aaa.baz' but now it results in '/aaa/.baz'.
2013-01-18 20:52:57 -08:00
danilsomsikov a26234f718 fix(ngSwitch): don't leak when destroyed while not attached
The leak can occur when ngSwich is used inside ngRepeat or any other
directive which is destroyed while its transcluded content (which
includes ngSwitch) is not attached to the DOM.

Refactor ngSwitch to use controller instead of storing data on compile
node. This means that we don't need to clean up the jq data cache.
Controller reference is released when the linking fn is released.

Closes #1621
2013-01-18 00:03:28 -08:00
Misko Hevery 61315211da fix(git-validator): support fixup and better errors 2013-01-17 23:52:46 -08:00
Misko Hevery af89daf464 feat(ngResource): support all $http.config actions
This allows the transformation of the $http request in both directions,
headers, caching, and timeout.
2013-01-17 23:08:39 -08:00
Fred Sauer 224d7d6e90 docs(exceptionHandler): document testing
Update src/ng/exceptionHandler.js

Here's an iniitla attempt at documenting how one might write a
test using $exceptionHandlerProvider. The key take-away is the use
of this pattern:

it(...

 module(...
   $exceptionHandlerProvider.mode('log');
 });

 inject(...
 );

});
2013-01-17 23:08:39 -08:00
Jeremy Tymes a179a9a96e feat($parse): allow strict equality in angular expressions
Allows the parser to parse strict equality and inequality
in angular expressions.

Closes #908
2013-01-17 23:08:38 -08:00
Matthew Browne 610a5a0c14 docs(rootScope): correct code examples 2013-01-17 23:08:38 -08:00
Amir H. Hajizamani 4f5583465a docs(cookbook): change prototype methods to scope methods in Buzz
As explained in 'Understanding the Controller Component', Controllers
written for new (post 1.0 RC) versions of Angular need to add methods to
the scope directly, not the function's prototype. Correcting this
example should remove any ambiguity, especially for beginners.
2013-01-18 00:49:41 -05:00
Amir H. Hajizamani 75487ec933 docs(guide): change prototype methods to scope methods in DI examples
As explained in 'Understanding the Controller Component', Controllers
written for new (post 1.0 RC) versions of Angular need to add methods to
the scope directly, not the function's prototype. Correcting this
example should remove any ambiguity, especially for beginners.
2013-01-18 00:49:41 -05:00
Fred Sauer dddb1221fa docs(ngMock.$httpBackend): fix variable declaration 2013-01-18 00:13:39 -05:00
Shai Reznik 69e4d40a76 doc(guide): Fixed typos at the unit tests guide 2013-01-17 23:43:13 -05:00
Shai Reznik d521619c58 doc(guide): Fix examples of $location.html5mode 2013-01-17 23:43:13 -05:00
Igor Minar 5ae63fd385 fix(angular.equals): consistently compare undefined object props
previously:

a = {};
b = {x:undefined};
angular.equals(a, b) == angular.equals(b, a) // returns false.

both should return false because these objects are not equal.

unlike in implemented in #1695 the comparison should be stricter
and return false not true. if we need to relax this in the future
we can always do so.

Closes #1648
2013-01-17 17:48:51 -08:00
Daniel Demmel 8b44324814 docs: recommend using Google CDN 2013-01-17 16:52:05 -08:00
nlaplante 9e991ddb1d feat($log): add $log.debug()
New debug() method with suppressable output via
$logProvider.debugEnabled()

Closes #1592
2013-01-17 16:47:39 -08:00
Matt Rohrer 93070f1488 docs(guide): minor grammar fixes 2013-01-17 19:10:46 -05:00
Gergely Imreh 3c8583e5dd chore(Rakefile): force 32bit JVM mode only when java supports it
Some Java installs don't have '-d32' flag (e.g. OpenJDK which is standard
for some Linux systems), and the closure_compile fails because of forcing
that flag. Test, and only run in faster 32bit mode if supported, or
else just run with no flag (default mode).
2013-01-17 01:34:01 -08:00
Igor Minar 78699c62ea chore(docs): use done() instead of end() in gen-docs.js 2013-01-17 00:51:56 -08:00
Pete Bacon Darwin 49f9e4cef1 fix($compile): do not wrap empty root text nodes in spans
Closes #1059
2013-01-17 00:28:44 -08:00
Pete Bacon Darwin 7e746015ea fix(ngRepeat): correctly apply $last if repeating over object
If the $last property is calculated from the original collectionLength
on an object and properties starting with $ were filtered out, then $last
is never applied and $middle is applied erroniously.

Closes #1789
2013-01-17 00:25:30 -08:00
James deBoer 8c269883fd chore(Rakefile): remove a duplicate file in angularFiles.js 2013-01-16 23:45:09 -08:00
James deBoer a69674b36d chore(Rakefile): generate version.json
Changes 'rake version' to output a version.json file which
contains the structured version info which can be used in other tools.
2013-01-16 23:41:45 -08:00
Igor Minar 8b9e6c3501 fix(scenario): don't trigger input events on IE9
input.enter() should trigger 'change' rather than 'input' event on IE9 because
input events on IE9 are broken and angular doesn't rely on them
2013-01-16 23:26:36 -08:00
Kanwei Li c97c53dbd4 docs(CHANGELOG): fix typo 2013-01-16 21:55:06 +01:00
Martin Probst c6392616ea fix($route): support route params not separated with slashes.
Commit 773ac4a broke support for route parameters that are not seperated
from other route parts by slashes, which this change fixes. It also adds
some documentation about path parameters to the when() method and
escapes all regular expression special characters in the URL, not just
some.
2013-01-16 09:41:02 -08:00
Igor Minar 74dd2f7980 fix($compile): safely create transclude comment nodes
Closes #1740
2013-01-14 21:57:23 -08:00
Lucas Galfasó c0cb9f8c14 doc(directive): Fix typos in dialog widget
Fixes #1799
2013-01-13 10:08:19 +00:00
Igor Minar 7dff7bb696 chore(*): remove obsolete files 2013-01-09 21:28:53 -08:00
Martin Probst cdf6fb19c8 feat($compile): support modifying the DOM structure in postlink fn
Support modifying the DOM structure in the post link function of a directive
by creating a defensive copy of the node list, as opposed to a live DOM list.
This is useful for directives to actually replace their entire DOM fragment,
e.g. with the HTML fragment generated by a 3rd party component (Closure, Bootstrap ...).
Fix the indentation of the compileNodes function (was one too little).
2013-01-09 20:06:22 -08:00
Igor Minar c909f49112 style($compile): fix indentation 2013-01-09 16:54:29 -08:00
Igor Minar cc821502bc fix(date): parse string input as local time unless TZ is specified
previously we were always parsing the string input as UTC which cased issues like:

{{ '2012-04-01' | date:'d MMM yyyy' }} renders as 31 Mar 2012

BREAKING CHANGE: string input without timezone info is now parsed as local time/date

Closes #847
2013-01-09 09:50:43 -08:00
naomiblack 037aefae47 Update docs/content/misc/faq.ngdoc
Updated the canonical video to a recent one. Fixed a typo.
2013-01-09 09:49:44 +00:00
Pete Bacon Darwin febb4c1c35 fix(jqLite): children() should only return elements
The jQuery implementation of children only returns child nodes of the given element that are elements themselves. The previous jqLite implementation was returning all nodes except those that are text nodes. Use jQLite.contents() to get all the child nodes.

The jQuery implementation of contents returns [] if the object has no child nodes.  The previous jqLite implementation was returning undefined, causing a stack overflow in test/testabilityPatch.js when it tried to `cleanup()` a window object.

The testabilityPatch was incorrectly using children() rather than contents() inside cleanup() to iterate down through all the child nodes of the element to clean up.
2013-01-09 09:22:35 +00:00
Keyamoon 76a6047af6 fix(jqLite): make next() ignore non-element nodes
next() is supposed to return the next sibling *element* so it
should ignore text nodes. To achieve this, nextElementSibling()
should be used instead of nextSibling().
2013-01-08 14:54:15 -08:00
Igor Minar b6b7c5a1d6 fix($injector): remove bogus fn arg
getService fn takes only one argument, removing the second one.

Closes #1711
2013-01-08 14:36:03 -08:00
Igor Minar 5b5f35d5e4 refactor($browser): remove faulty 20+ cookies warning
the warning is defunct (and the test is incorrect) so obviously nobody is using
it and it just takes up space.

also the browser behavior varies (ff and chrome allow up to 150 cookies, safari
even more), so it's not very useful.

Closes #1712
2013-01-08 14:23:50 -08:00
Igor Minar 14948cf5d9 revert: fix(a): prevent Opera from incorrectly navigating on link click
This reverts commit c81d8176cc.

This commit causes several issues (#1651, #1674, #1662) and doesn't even
contain a test that proves that anything on Opera got actually fixed.

If the original Opera resurfaces, we'll fix it properly.
2013-01-08 11:47:22 -08:00
kim lokoy 2b0978b07c docs(guide): fix typos in unit test guide 2013-01-07 21:01:01 +01:00
Pawel Kozlowski 1122dc7a5b docs(forms): fix code example for a custom form control
Closes #1021
2013-01-05 22:47:36 +01:00
naomiblack a3a9d4af05 docs(faq): add info on logo reuse and how to get t-shirts and stickers 2013-01-04 18:59:11 +01:00
Jonathan Card 36089931a5 docs(form): minor form doc and example fixes
Form documentation fixes:
- Fix broken form example in docs
- A few small other corrections in form docs.
2013-01-04 09:28:35 +01:00
Per Rovegård 74db36ee94 docs($http): clarify documentation on error status codes
Modify the documentation for $http to correspond to what Angular
considers a success status code.

Closes #1693
2013-01-03 20:49:43 +01:00
Matt Hardy 8d42ce8563 docs(guide): change example controller to properly call greet method on greeter 2012-12-31 12:49:51 +01:00
petrovalex f0c6ebc076 feat($timeout-mock): add verifyNoPendingTasks method
added verifyNoPendingTasks method, which throws error if not all
deferred tasks have been flushed

Closes #1245
2012-12-20 20:39:40 +01:00
Murilo da Silva 59d9b89852 docs(anchorScroll): correct word "location" 2012-12-19 21:01:41 +01:00
John Fletcher 6aac69039e docs(guide): minor English corrections to the Directive guide 2012-12-19 20:35:31 +01:00
Jeremy Tymes 9e96d98345 feat(limitTo): limitTo filter accepts strings
This allows strings to be filtered by limitTo, using the same methods

Closes #653
2012-12-19 20:13:36 +01:00
Miško Hevery 1e13544da8 docs(directive): old syntax 2012-12-18 20:38:43 -08:00
Mark Nadig e03182f018 feat(directive): ng:keydown, ng:keyup
New directives for binding to keydown and keyup events.

Closes #1035
2012-12-18 22:57:58 +01:00
Pawel Kozlowski f2d526190a docs(ngView): fix code example (change template to templateUrl)
Closes #1715
2012-12-17 23:18:12 +01:00
Miško Hevery 039b138042 docs(q): added testing information 2012-12-14 05:49:22 -08:00
Gonzalo Ruiz de Villa 30a9da5dc1 fix($route): correctly extract $routeParams from urls
Routes like '/bar/foovalue/barvalue' matching '/bar/:foo/:bar'
now are well mapped in $routeParams to:
{bar:'barvalue', foo:'foovalue'}

Closes: #1501
Signed-off-by: Gonzalo Ruiz de Villa <gonzaloruizdevilla@gmail.com>
2012-12-14 01:15:15 +01:00
ggoodman 25e1ad9a94 feat(docs): Add angularjs tag to plunks and make private
This is a minor edit to allow Plunks created by way of the docs.angularjs.org site to be appropriately tagged as `angularjs`.
Also, make these generated Plunks private by default.
2012-12-11 19:04:46 +00:00
Peter Evjan 37cced6296 docs(README.md): add missing 'you' and a comma 2012-12-11 19:20:30 +01:00
Romain Neutron a66c968df2 docs(guide): fix injector service code example
Fix syntax and update code to the latest API
2012-12-10 23:19:20 +01:00
Juha Syrjälä c398d7d370 docs($resource): document port number escaping and fix typo
Closes #1243
2012-12-09 17:13:29 +01:00
Eric Case d93533812b docs(tutorial): typo fix commandx -> command 2012-12-08 11:33:07 +01:00
Eric Case ff11061a8f docs($q): typo fix - programing -> programming 2012-12-07 20:45:33 +01:00
János Rusiczki c52bfd37ee doc(concepts): Fix typo in $render() function 2012-12-07 10:03:58 +00:00
Jeremy Tymes f8b755982a docs($http): fix link typo in $http doc
Should be $httpBackend instead of $httpBacked

Closes #1516
2012-12-06 21:25:47 +01:00
Fred Sauer bcc7089b3c docs(mocks): update src/ngMock/angular-mocks.js documentation
Clarify how to use `$exceptionHandlerProvider.mode('log')` in tests
2012-12-06 21:18:49 +01:00
Fred Sauer d43cc3f893 docs(mocks): fix documentation bug: angular.mock.debug 2012-12-06 21:13:51 +01:00
Igor Minar c9d937082c chore(bootstrap-prettify): update urls to code.angularjs.org
Closes #1599
2012-12-05 02:55:43 +01:00
_pants 26adeb119b fix(select): support optgroup + select[multiple] combo
Closes #1553
2012-12-05 02:20:11 +01:00
Stephane Bisson 15183f3e1f feat(e2eRunner): fail when an option to select does not exist 2012-12-01 20:05:42 +01:00
Sudhir Jonathan 2c405f4171 fix($injector): provider can now be defined in the array format
`injector.instantiate` is now called for arrays too, instead of only for functions.

Closes #1452
2012-12-01 18:41:59 +01:00
Sudhir Jonathan 8991680d8a fix($resource): HTTP method should be case-insensitive
Perform call `angular.uppercase` on all given action methods.

Closes #1403
2012-11-30 22:58:11 +01:00
Cezar Berea ec801ac137 refactor($resource): fix indentation and move a method definition
Moved Resource.bind out of the actions forEach
2012-11-30 22:35:57 +01:00
Igor Minar d6da505f4e fix(Scope): ensure that a scope is destroyed only once
Due to bd524fc4 calling $destroy() on a scope mupltiple times cases NPE.

Closes #1627
2012-11-30 13:10:00 +01:00
Daniel Luz 5f7054bf5d docs(directive): correct expression, fix typo and re-wrap lines 2012-11-29 19:40:33 +01:00
Johannes Hansen cf4ed8a145 fix(docs): add missing </div> tag to sourceEdit directive template 2012-11-29 19:40:30 +01:00
Igor Minar d1e48fcbf3 docs(menu): fix the navbar drop down links 2012-11-28 23:56:09 +01:00
Pascal Corpet cc42c99bec feat($resource): allow dynamic default parameters
Default resource params can now be calculated at runtime if defined
via a function.
2012-11-28 16:01:57 +01:00
Igor Minar 3c7bfa77aa chore(release): start 1.1.2 tofu-animation iteration 2012-11-28 14:21:33 +01:00
Igor Minar 2ee0f56c54 chore(release): cutting the 1.1.1 pathological-kerning release 2012-11-27 01:45:35 +01:00
Igor Minar 9b18644f30 docs(CHANGELOG): release notes for 1.0.3 and 1.1.1 releases 2012-11-27 01:43:05 +01:00
Rado Kirov fce100a46c fix($http): only set X-XSFR-TOKEN header for same-domain request
This is needed to prevent CORS preflight checks. The XSFR token
is quite useless for CORS requests anyway.

BREAKING CHANGE: X-XSFR-TOKEN is no longer send for cross domain
requests. This shouldn't affect any known production service.

Closes #1096
2012-11-26 23:58:59 +01:00
Rado Kirov 3a75b1124d fix($http): remove 'X-Requested-With' from header defaults
X-Requested-With header is rarely used in practice and by using
it all the time we are triggering preflight checks for crossdomain
requests.

We could try detecting if we are doing CORS requests or not, but
it doesn't look like it's worth the trouble.

BREAKING CHANGE: X-Requested-With header is not set by $http service
any more. If anyone actually uses this header it's quite easy to add
it back via:

```
myAppModule.config(['$httpProvider', function($httpProvider) {
    $httpProvider.defaults.headers.common["X-Requested-With"] = 'XMLHttpRequest';
}]);
```

Closes #1004
2012-11-26 23:36:40 +01:00
Rado Kirov a32bc40fd7 fix($location): reset $location.$$replace with every watch call
Closes #1111
2012-11-26 23:21:02 +01:00
Igor Minar cfe13b5dac chore(validate-commit-msg): recognize 'revert' as valid commit type 2012-11-26 21:05:38 +01:00
Igor Minar d859dcecea fix(ngClassOdd/ngClassEven): support shrinking/reordering in repeaters
We need to watch $index in addition to cssClasses because only then
we can correctly respond to shrinking or reordered repeaters.

Closes #1076
2012-11-26 20:36:53 +01:00
Igor Minar d3b32a7c94 style(jqLite): better variable names
selector => cssClasses
2012-11-26 20:36:53 +01:00
Igor Minar 1b17dfa693 fix(ngRepeat): support mostly-stable repeating for primitives
I'm reverting changes that were originally done to ngRepeat to fix #933,
because these are now not necessary after the previous changes to keep
ngModel always synced with the DOM.
2012-11-26 20:36:53 +01:00
Igor Minar e6d9bea4f3 fix(ngModel): sync ngModel state with scope state
In cases when we reuse elements in a repeater but associate
them with a new scope (see #933 - repeating over array of
primitives) it's possible for the internal ngModel state and
the scope state to get out of sync. This change ensure that
the two are always sync-ed up even in cases where we
reassociate an element with a different (but similar) scope.

In the case of repeating over array of primitives it's still
possible to run into issue if we iterate over primitives and
use form controls or similar widgets without ngModel - oh well,
we'd likely need a special repeater for primitives to deal
with this properly, even then there might be cornercases.

Closes #933
2012-11-26 20:36:53 +01:00
Igor Minar c8e9105fe6 test(ngRepeat): clean up and improve tests 2012-11-26 20:36:52 +01:00
Igor Minar d644dcfa52 fix(ngRepeat): attempt to simplify and improve existing fix for #933
I'm keeping this in for future reference. The issue with this solution
is that if we shift() the first item in the array, the whole repeater
DOM will be rebuilt from scratch, we need to do better than that.
2012-11-26 20:31:54 +01:00
Igor Minar e7d37ee45a test(ngRepeat): add test for issue #1076 2012-11-26 20:17:11 +01:00
Pawel Kozlowski 733a97adf8 feat(form): add ability to reset a form to pristine state
Retting a form to pristine state will cause all of the nested
form and form controls to be recursively reset as well.

Closes #856
2012-11-26 16:44:34 +01:00
Igor Minar 96ed9ff59a fix(jqLite): support append on document fragment
previously jquery didn't support append on this node type, now it does
(since 1.8.x) so I'm adding this to jqlite as well.
2012-11-26 15:45:04 +01:00
Igor Minar b9a9f91fbf fix(jqLite): fire $destroy event via triggerHandler
in jQuery 1.8.x the data() data structure is changed and events are
not accessible via data().events. Since all we need is to trigger
all event handlers, we can do so via triggerHandler() api instead of
mocking with the internal jQuery data structures.

This fix was originally proposed by PeteAppleton via PR #1512.

Closes #1512
2012-11-26 15:45:04 +01:00
Igor Minar 650fd933df feat(jqLite): add triggerHandler()
we need triggerHandler() to become jQuery 1.8.x compatible.

this is not fully featured triggerHandler() implementation - it doesn't
bother creating new DOM events and passing them into the event handlers.

this is intentional, we don't need access to the native DOM event for our
own purposes and creating these event objects is really tricky.
2012-11-26 15:45:04 +01:00
Igor Minar e249502880 chore(jquery): upgrade to jquery 1.8.2 2012-11-26 15:45:04 +01:00
Iristyle ca3e0e7374 docs(CONTRIBUTING.md): add contrib info file for GitHub 2012-11-25 21:00:14 +01:00
Vojta Jina e6966e05f5 fix(Scope): allow removing a listener during event 2012-11-25 11:39:54 +01:00
Kevin Western 682418f029 docs(README.md): fix "API Docs" link
use direct link to api docs
2012-11-25 01:21:52 +01:00
Dean Sofer c8fd7fd0e2 docs(api): add ngRequired to input/select/textarea directives
Closes #1202
2012-11-25 01:18:10 +01:00
JP Sugarbroad 168db33985 feat($cacheFactory): cache.put now returns the added value
This allows common programming patterns to be expressed with more
concise code.

See #1583 for code examples.
2012-11-25 00:01:34 +01:00
Tom Davis 79af2badcb fix($http): config.param should expand array values properly
Today, calling e.g. $http(url, { params: { a: [1,2,3] } }) results in a query
string like "?a=%5B1%2C2%2C3%5D" which is undesirable. This commit enhances
buildURL to createa query string like "?a=1&a=2&a=3".

BREAKING CHANGE: if the server relied on the buggy behavior then either the
backend should be fixed or a simple serialization of the array should be done
on the client before calling the $http service.

Closes #1363
2012-11-24 22:26:23 +01:00
Zach Dexter 610927d77b feat(linky): allow optional 'target' argument
Closes #1443
2012-11-24 22:21:50 +01:00
Jeremy Tymes 55d15806fb fix($cacheFactory): return undefined when removing non-existent entry
Instead of throwning an exception, remove should return undefined when
cache entry to be removed doesn't exist.

Closes #1497
2012-11-24 21:56:28 +01:00
Adrian Gheorghe 94e1c0391c fix($resource): prevent default params to be shared between actions
Having a $resource defined as:

var R = $resource('/Path', {}, {
  get: {method: 'GET', params: {objId: '1'}},
  perform: {method: 'GET'}
});

was causing both actions to call the same URI (if called in this order):

R.get({}); // => /Path?objId=1
R.perform({}); // => /Path?objId=1
2012-11-24 21:27:24 +01:00
Kris Jenkins b21f4a376d docs(): Fix a couple of typos in the documentation 2012-11-21 23:06:59 +01:00
Dave Clayton f28f283fcf docs(guide/concepts): some typo/grammar fixes 2012-11-17 23:55:32 +01:00
John Hume e362a510e3 docs(guide/directive): fix typo 2012-11-17 23:49:19 +01:00
Uri Goldshtein 8a7f752a80 docs($q): fix missing bracket in the example 2012-11-17 23:45:08 +01:00
Igor Minar af7e0bd0a7 fix(CSP): update to the latest CSP api
window.SecurityPolicy.isActive() is now window.securityPolicy.isActive

since this is available only in Chrome Canary which has already been
updated, we can safely make this change without worrying about
backwards compatilibty.

Closes #1577
2012-11-15 01:46:58 +01:00
Igor Minar bd524fc4e5 fix($rootScope): workaround for Chrome's memleak
Under certain circumstances chrome fails to GC scopes
because of buggy optimizations and caching. Nulling out
references to (not from!) other scopes helps Chrome to
realize that this object should be GC-ed.

This is really just a workaround as the real problem needs
to be fixed in Chrome.

See discusstion at:
https://github.com/angular/angular.js/issues/1313#issuecomment-10378451

And chrome bug at:
https://code.google.com/p/v8/issues/detail?id=2073

Closes #1313
2012-11-14 19:56:28 +01:00
Haralan Dobrev 19a324ce11 docs(angular.module): improve angular.Module#run docs 2012-11-11 11:40:18 +01:00
Jamison Dance cd8b78ebfd docs(guide): fix run-on sentence in modules guide 2012-11-11 11:34:06 +01:00
Jamison Dance 8891757891 docs(tutorial): change module name in step-7 2012-11-11 11:34:06 +01:00
Wes Alvaro 5c5193946d docs($timeout): set return type to Promise instead of *.
The cancel function accepts a Promise, but the timeout function
fails to specify returning a Promise.
2012-11-11 11:31:51 +01:00
Josh Adams ffa6c5195f docs(ngList): fix typo 2012-11-11 11:24:59 +01:00
Josh Adams a758799c7f docs(encodeUriSegment): fix typo 2012-11-11 11:22:43 +01:00
Tim Macfarlane e9253a88b9 docs(guide/directive): fix names in scope '='; easier to grok 2012-11-11 11:20:24 +01:00
Christian Vuerings f3e053cb6f docs(ngHide): Fix typo and make it more in line with ngShow 2012-11-11 10:36:28 +01:00
Anna Vester 04450c48df feat($sanitize): support telephone links
Per http://www.ietf.org/rfc/rfc3966.txt support tel: links
2012-11-11 10:31:27 +01:00
Igor Minar 8650843603 chore(docs): fix docs-scenario.html 2012-11-11 10:31:27 +01:00
Igor Minar e034fa08a8 chore(docs): remove obsolete gae files 2012-11-11 10:31:27 +01:00
Miško Hevery c6b4ab3548 Update docs/content/guide/directive.ngdoc
docs(directive): fix typo
2012-11-05 19:34:20 -08:00
Sudhir Jonathan b429f538a3 chore(testacular): use local testacular version
Making testacular a dependency to avoid having to install it globally.
(Causes npm issues on some machines)
2012-10-31 16:47:28 -07:00
Sudhir Jonathan b3cae4f457 fix(select): select option with a label of 0 is not shown
Bug caused by the use of the `||` operator to replace all non-truthy
values with an empty string. Changed to replace only `undefined` values.

Closes #1401
2012-10-31 15:03:13 -07:00
Igor Minar 7b52a976e1 chore(validate-commit-msg): allow '/' in scope 2012-10-31 14:47:59 -07:00
Fred Sauer 3a624a7ff5 docs(guide/location): fix table formatting
Fix table formatting so headings are bold, rows are separated by lines, and rows have :hover style
2012-10-31 14:47:53 -07:00
Tim Macfarlane b32adb7dea docs(module): fix typo in example
fixed example app, `simpleAppModule` should have been `myAppModule`.
2012-10-31 14:21:28 -07:00
sqwishy trick 271d2bed3a chore(injector): fix typo in injector documentation 2012-10-31 14:19:05 -07:00
Adam Macejak 249a1d84e7 fix(scenario-runner): support data-ng and x-ng based attributes
Prefixed attributes like data-ng-model and x-ng-model were not being
found by the Selector. It was only looking at ng: and ng- prefixed
attributes.
Added a few tests as well to ensure the aforementioned prefixed
attributes are being matched properly.

Closes #1020
2012-10-31 13:58:13 -07:00
Daniel Luz fdf85bfd86 docs(contribute): fix task name for continuous testing 2012-10-31 13:12:49 -07:00
Igor Minar 090e5426ac fix(docs): correctly generate filenames for plunkr/fiddle
previously examples like $http where broken because we would strip part of the
filename (http-hello.html -> http)

we really want to strip only the id suffix that we append to disambiguate
common filenames (like index.html) which appear in many examples.
2012-10-31 13:03:50 -07:00
Shyam Seshadri 7c67b2fb6a feat(docs): add plunkr support
Add option to edit source in Angular Docs in Plunkr in addition to JsFiddle
2012-10-31 12:54:52 -07:00
Daniel Luz 3c9b39ff52 fix(doc): typo on FAQ
Closes #1493
2012-10-31 10:24:12 -07:00
Igor Minar 54b3875ba5 fix($compile): don't look for class directives in empty string
if className is undefined or empty string, don't bother looking for directives in there
2012-10-29 17:49:56 -07:00
Igor Minar 008a782bc8 fix($compile): compilation should not recurse into empty nodes
if a node doesn't have children then don't try to compile these non-existent children
2012-10-29 17:49:36 -07:00
Igor Minar 524c5c8b5d style($compile): better fn names for debugging 2012-10-29 17:46:44 -07:00
Igor Minar b936236fbc refactor(): simplify nodeLinkFn 2012-10-29 17:46:44 -07:00
Igor Minar fc115bfd0d fix($compile): prevent double attr interpolation w/ templateUrl
This fixes the issue that caused two attr interpolation observers
to be registered for the same attribute as a result of isolate
scope definition with attr (@) property for this attribute.

Duplicate observers would then fight with each other updating the
model.

The issue occured only when this directive was used in a repeater
because that's when we clone the template node which caused the
two observers to point to two different sets of $attr instances.

Closes #1166, #836
2012-10-29 17:46:44 -07:00
Braden Shepherdson bca1604c12 fix(currency): Handle not-quite-zero values
IEEE 754 floating point sometimes results in values that are very small,
rather than zero. One example is 1.0 + 1.07 - 2.07, which returns
4.440892098500626e-16 instead of 0.

This change tweaks the number formatting logic so that an exponential
value with a negative exponent that is larger than the precision+1
returns 0 instead. For example: with precision 2, anything with an
exponent of -4, -5 or more would become 0. 9e-3 = 0.009 = 0.01, but 9e-4
= 0.0009 = 0.001 = 0.00. This detail is unlikely to matter since this
quirk is usually only triggered with values very close to zero.

Closes #1469
2012-10-26 08:51:28 -07:00
Braden Shepherdson f4517b500c doc(faq): Add Common Pitfalls section
Describes several common pitfalls new users of Angular fall into that
I've observed in #angularjs.
2012-10-26 08:49:44 -07:00
Braden Shepherdson f54edbbdd4 doc(faq): Fix minor spelling and wording errors 2012-10-26 08:49:44 -07:00
Igor Minar be50e0769a chore(check-size.sh): fix rake target 2012-10-22 12:39:37 -07:00
Igor Minar cf78fb5661 docs(contribute): add CLA note to code submission section 2012-10-19 09:14:05 -07:00
Igor Minar 5c9eb75867 docs(contribute): add visible link to github project 2012-10-19 09:02:06 -07:00
Igor Minar f43cf3b816 chore(jstd-scenario-adapter): remove from our repo
since we don't need the adapter for JsTD (testacular contains its own),
I'm removing this dead code.
2012-10-18 03:26:51 -07:00
Igor Minar 175e727f05 chore(validate-commit-msg): allow * and - in scope string 2012-10-18 03:26:08 -07:00
Igor Minar d938983c06 chore(jasmine): remove Jasmine from our repo
it's bundled with Testacular, so we don't need it here
2012-10-18 03:14:27 -07:00
Igor Minar 8d69f4b93a chore(jstd): remove JsTestDriver from our repo
Testacular FTW!
2012-10-18 03:13:04 -07:00
Igor Minar ca96ec32f9 docs(tutorial): replace JsTD with Testacular + drop snapshots
JsTD references have been replaced with Testacular stuff.

snapshots are PITA to maintain so I'm dropping them, everyone loves the Git
version anyway.
2012-10-18 02:33:45 -07:00
Igor Minar 4f59022582 chore(Rakefile): remove test_out dir when cleaning 2012-10-17 15:44:18 -07:00
Igor Minar 3bd95dbb1a chore(Rakefile): tune JVM for closure compiler
Using the client VM and forcing 32bit mode gives us huge perf boost.

before:

reali   0m8.173s
user    0m39.984s
sys     0m1.408s

after:

real    0m3.000s
user    0m12.687s
sys     0m0.852s
2012-10-17 15:36:51 -07:00
Igor Minar c959fa4fe8 chore(Rakefile): paralelize closure compilation
this speeds up the build by paralelizing closure compilation (the slowest
piece of the build process)

before:

real  0m14.372s
user  0m31.649s
sys   0m1.006s

after:

real  0m8.191s
user  0m40.473s
sys   0m1.378s
2012-10-17 14:38:15 -07:00
Vojta Jina a5d434d857 chore(test): add junit config for testacular 2012-10-17 13:17:16 -07:00
Igor Minar 0ae0591f42 chore(Rakefile): misc_options should support + -> , conversion 2012-10-17 12:48:08 -07:00
Igor Minar 43ac783d35 chore(Rakefile): use exec for webserver
exec unlike system replaces the current process. this way when we kill
the webserver process we don't get scary looking 'rake aborted' error
2012-10-17 12:45:10 -07:00
Misko Hevery c96dc60594 fix(doc): disable directory listing in docs.angularjs.org 2012-10-05 16:43:01 -07:00
Igor Minar b440ad36f3 docs(downloading): update the downloading docs 2012-10-05 03:13:51 -07:00
Vojta Jina 8b2532cec7 chore: add travis config 2012-09-24 23:39:33 -07:00
Vojta Jina 8db47ca7d4 fix($compile): reference local in isolate scope
This was really corner case:
Watcher needs to return changed value, to notify that model might have changed and one more $digest cycle needs to be performed.

The watcher, that takes care of reference binding into an isolate scope ("="), did not return changed value, if the change was from the isolate scope to the parent.

If any other watcher returned change, it worked fine, as this change caused re-digest.

Closes #1272
2012-09-20 18:32:01 -07:00
Vojta Jina bcaa3bb373 docs: load angular from CDN only on production
So that when running the docs locally, eg. during e2e testing, we use the latest build version of angular, rather than the stable one from CDN.

This fixes e2e tests running with Testacular.
2012-09-17 18:08:16 -07:00
Igor Minar 6fc4fdb438 docs(README): update README.md with new rake tasks 2012-09-17 14:51:21 -07:00
Igor Minar 6a5f8c0483 chore(Rakefile): fix test:jquery task 2012-09-17 14:50:51 -07:00
Igor Minar 20c116d9d5 docs(contribute): update contribute docs 2012-09-16 10:40:44 -07:00
Igor Minar 4a04c2ec0c chore(): remove unused files 2012-09-16 10:39:43 -07:00
Igor Minar 89dd566277 docs(contribute): update misc/contribute docs with Testacular info 2012-09-15 08:11:53 -07:00
Igor Minar 9d168f058f chore(testing): Testacular config files + rake tasks
- adds testacular config files for jqlite, jquery, modules and e2e tests
- replaces obsolete JsTD Rake tasks with Testacular onces
- rake tasks are parameterazied so that they can be used locally as well as on CI server

usage:

rake test  # run all tests on Chrome
rake test[Safari+Chrome+Opera]  # run all tests on Safari, Chrome and Opera
rake test[Safari]  # run all tests on Safari
rake test:jqlite # run unit tests using jqlite on Chrome
rake test:jqlite[Safari,"--reporter=dots"]  # run jqlite-based unit tests on Safari with dots reporter
rake autotest:jquery  # start testacular with jquery-based config and watch fs for changes
rake test:e2e # run end to end tests
2012-09-13 16:23:18 -07:00
Miško Hevery 5418564f04 docs(directive): remove reference to old isolation syntax 2012-09-13 11:31:06 -07:00
Misko Hevery b0a05a7531 fix($route): support inline annotation on .resolve 2012-09-11 22:10:26 -07:00
Tom Hughes 209b67df6a feat($http): Allow setting withCredentials on defaults
Closes #1095.
2012-09-11 21:59:31 -07:00
Vojta Jina 2e1539356a chore(scripts): add init-repo script 2012-09-11 17:27:57 -07:00
Misko Hevery 331cd5a8cb fix($evalAsync): have only one global async queue
Having one async queue per scope complicates the matters when users wish to do
partial scope updates, since many services put events on the rootScope. By
having single queue the programing model is simplified.
2012-09-11 16:12:41 -07:00
Brian Ford f2ebfa16b0 docs(guide): fix directive interpolation example code
Closes #1339
2012-09-11 16:12:41 -07:00
Shyam Seshadri 95276a7e10 fix(scenario): emit RunnerBegin event 2012-09-11 16:12:41 -07:00
Vojta Jina 5dbd942bac chore(scripts): add commit-msg hook (validation) 2012-09-11 16:12:40 -07:00
Jimmy Zhuo 84c13d96ff fix(scenario): NPE when no angular loaded in test page 2012-09-11 16:12:40 -07:00
Daniel Luz 79941d2527 docs($rootScope): fix iteration limit described by $watch, it's actually 10 as of now 2012-09-11 15:11:02 -07:00
Daniel Luz 03ebecd5eb docs($rootScope): fix typos and minor wording tweaks on $watch 2012-09-11 15:11:02 -07:00
Daniel Luz 62bb728d07 docs($rootScope): fix quoting on expression 2012-09-11 15:11:02 -07:00
Daniel Luz b8eb843b25 docs($rootScope): standardize on present, third-person actions for descriptions 2012-09-11 15:11:02 -07:00
Daniel Luz 053247e412 docs($rootScope): backquote attribute types too on $on 2012-09-11 15:11:02 -07:00
Daniel Luz 7fa391c979 docs($cacheFactory): fix backquotes on method descriptions 2012-09-11 15:11:01 -07:00
Daniel Luz b01c28c900 docs($rootScope): fix typos on $new 2012-09-11 15:11:01 -07:00
Daniel Luz c0b9e94dec docs($rootScope): fix typo on $eval 2012-09-11 15:11:01 -07:00
Daniel Luz 83fbdd1097 docs($rootScope): fix typos on $watch 2012-09-11 15:11:01 -07:00
Jay Zeng 03042c52b9 docs(ngResource): Spelling typo (agressive => aggressive) 2012-09-11 15:08:55 -07:00
Igor Minar 2a4a8226d1 fix($resource): fix isDefined -> angular.isDefined 2012-09-10 14:49:22 -07:00
sgtpep c81d8176cc fix(a): prevent Opera from incorrectly navigating on link click
we handle the navigation by ourselves, so we need to prevent the default action.

Opera ignores event.preventDefault() call so we must return false.
2012-09-06 16:06:27 -07:00
Kai Groner 04329151d2 fix(FormController): propagate dirty state to parent forms 2012-09-06 16:06:26 -07:00
Jonathan Zacsh a9be003fce chore(docs): get correct location for jasmine-node 2012-09-06 16:06:25 -07:00
Shyam Seshadri ca30fce28c fix(*): name all anonymous watch functions in Angular
This will allow us to see function names in Batarang and debugger.

Closes #1119
2012-09-06 16:06:25 -07:00
Xiangru Chen b6e4a71166 fix(ngSrc): don't set src if value is empty string
Current implementation of ngSrc may lead to empty src attribute when page is loading.

For example:

<img ng-src="{{image.url}}">
can be temporarily rendered as

<img src="">
before the image resource is loaded.

Some browser emits a request to the current page when seeing <img src=""> (Firefox13 and IE8 will, Chromium20 won't), which leads to performance problems.
2012-09-06 16:06:24 -07:00
Misko Hevery d9eff86ef7 fix($injector): more conservative annotation parsing 2012-09-06 16:06:24 -07:00
Pedro Del Gallego 8cb9c99ec0 feat(scenario): add dblclick method to the ngScenario dsl 2012-09-06 16:06:24 -07:00
Iwein Fuld 9473780e77 fix(dateFilter): make timezone optional
Makes the time zone optional in the date filter

Problem with the current R_ISO8601_STR regex was that the time was optional, but the zone was not.
This results in the filter not formatting local date times, which it could easily do.

For example:
2012-08-30 -> formatted
2012-08-30T06:06:06.123Z -> formatted
2012-08-30T06:06:06.123 -> NOT formatted

A simple change in the regex fixes this. Arguably this is closer to the ISO8601 spec which specifies
local dates being in the "current time zone" and not requiring a Z. In any case it behaves more like
a user would expect.
2012-09-06 16:06:23 -07:00
Misko Hevery eb5fd400d3 docs(concept): correct example for creating injector 2012-09-06 16:06:23 -07:00
Godmar Back 0472c5f07e docs(module): fixed module example and corrected typos 2012-09-06 16:06:23 -07:00
Cameron Westland 92558fe411 feat(mocha): support mocha in angular mocks 2012-09-06 16:06:23 -07:00
Gregory Pike d519953a4b feat(ngModel): support ngTrim attribute on input 2012-09-06 16:06:23 -07:00
Benjamín Eidelman 4909d1d39d fix($resource): allow falsy values in URL parameters
Close #1212

when a param value was 0 (or false) it was ignored and removed from url.
after this fix that only happens if the value is undefined or null.
2012-09-06 16:06:22 -07:00
Jay Zeng 7079ff5eb6 docs(module): myAppModule -> simpleAppModule 2012-09-06 16:06:22 -07:00
petrovalex 10e1c759f4 fix($resource): ignore undefined parameters
- $resource should handle multiple params with same name
- ignore slashes of undefined parameters
- fix default parameters issue, mentioned in #875

Closes #875
Closes #782
2012-09-06 16:06:22 -07:00
petrovalex 6c67719dfa fix(ngClassEven/Odd): filtering/ordering and repeater
Closes #1076
2012-09-06 16:06:22 -07:00
Max Martinsson cebd015f78 fix(ngClass): works with class interpolation
Closes #1016
2012-09-06 16:06:21 -07:00
Max Martinsson fbdab513dd feat($resource): support custom headers per action
Closes #736
2012-09-06 16:06:21 -07:00
Zhenbo Zhang f2b7fffdc0 fix(ngRepeat): now works with primitive types
closes #933
2012-09-06 16:06:21 -07:00
petrovalex 42c38b29f7 fix($parser): string concatination with undefined model
Closes #988
2012-09-06 16:06:21 -07:00
Stein Jakob Nordbø f299fd5122 fix(dateFilter): support sub-second precision on dateFilter 2012-09-06 16:06:19 -07:00
Igor Minar 05c88b866b docs($route): rename leftover $afterRouteChange to $routeChangeSuccess 2012-09-06 15:03:35 -07:00
Igor Minar 9b08bfa251 chore(release): prepare 1.1.1 pathological-kerning iteration 2012-09-06 10:41:23 -07:00
Misko Hevery 99a000bac2 fix(docs): broken url to angular-bootstrap 2012-09-04 18:15:00 -07:00
Igor Minar f353fea042 chore(Rakefile): add 'version' rake task to generate version.txt 2012-09-04 16:38:01 -07:00
Igor Minar b1f50307b3 chore(docs): bump up the stable version 2012-09-04 16:31:57 -07:00
Igor Minar d0c0eadedd chore(release): cut the 1.1.0 increase-gravatar release 2012-09-04 11:11:09 -07:00
Igor Minar b8fac353f0 chore(docs): don't rewrite colons in doc filenames 2012-09-04 11:11:09 -07:00
Igor Minar b22308152f chore(Rakefile): zip only the build dir 2012-08-31 13:59:03 -07:00
Igor Minar 5e9041818b revert: fix(ng-repeat) to work with primitive types
this was accidentaly merged in. the commit is not ready yet
and we don't have CLA signature.

This reverts commit 98d489712e.
2012-08-31 13:59:03 -07:00
Igor Minar db861db1f2 docs(changelog): release notes for 1.0.2 and 1.1.0 releases 2012-08-31 13:59:03 -07:00
Jonathan Zacsh b12d1b6813 fix(docs): Making sure gen_docs.sh looks for a globally installed copy of jasmine-node as well as local. 2012-08-30 22:33:30 -07:00
Fernando Correia acb499f820 docs(tutorial): correct typos and clarify a few sections 2012-08-30 22:19:34 -07:00
Brice Burgess 9a710c788d fix(docs): indicate support for passing a string as the controller property on $routeProvider's route object 2012-08-30 22:13:20 -07:00
brettcannon 1b34c6d558 doc(misc) Mention how attribute names map to directive names. 2012-08-30 22:09:16 -07:00
Igor Minar a62c7b8b4e test(locationSpec): fix broken tests after vojta's commit 2012-08-30 16:25:23 -07:00
Sahat Yalkabov 62cfedbe0c doc(module) changed simpleApp to myApp in the Module page guide for consistency 2012-08-30 16:10:39 -07:00
Steve Nicolai 5cb7297a08 doc(devguide) - Fix typos and small grammatical errors in the developer guide. 2012-08-30 16:02:24 -07:00
Igor Minar 0f05516d14 chore(docs): ask GAE to serve docs-keywords.js 2012-08-30 15:58:55 -07:00
Uri Goldshtein f5f1200f25 Loading from Google CDN
As you guys had mansion, we can and need to do it through Google CDN for better performance,
so i've updated it accordingly
2012-08-30 15:49:11 -07:00
Tyson Benson c023c850c3 docs(typos): fix typos in dev guide 2012-08-30 15:43:58 -07:00
German Galvis 5318588d6e fix(scenario): Adding meta tag to avoid cache issues 2012-08-30 15:36:42 -07:00
phil 14c8f6a7ca docs(api): fix typo on home page
Refference -> Reference
2012-08-30 15:31:29 -07:00
csugden 351deb555f Update docs/content/guide/overview.ngdoc
Corrects video information
2012-08-30 15:28:15 -07:00
Jamie Krug 847d2da0f8 fix(docs): Fix typos and improve grammar. 2012-08-30 15:25:21 -07:00
Jamie Krug dbefd671e4 fix(docs): Fix bad links. 2012-08-30 15:25:20 -07:00
Colin Frei aff68a9ddf docs(module) fix typo 2012-08-30 15:22:08 -07:00
Zhenbo Zhang 0a71753ce3 fix(ng-repeat) to work with primitive types 2012-08-30 15:20:40 -07:00
Vojta Jina 1a8642aac2 fix(mocks): free up memory after every spec 2012-08-30 15:18:09 -07:00
Igor Minar 8114d55a15 test(bootstrap): test exception siling during bootstrap
Closes #1018
2012-08-30 15:15:11 -07:00
Igor Minar 9398040a41 test(ngApp): add missing test for [ng-app] bootstrap 2012-08-30 15:15:11 -07:00
Brian Ford d804bbcd51 feat($interpolate): provide contextual error messages
if an exception occurs during interpolation of a string
(e.g. name() in "Hello, {{name()}}!" throws an exception) we now print
an error message with the expression that was being evaluated when the
exception was thrown.
2012-08-30 14:50:22 -07:00
Igor Minar d3fa7a2e9e fix(jqLite): better support for xhtml
it turns out that some stuff doesn't work in xhtml as it does in html.

for example &nbsp; can't be innerHTML-ed and auto-closing of elements
doesn't work.

the reporter of the referenced issue claimed that innerHTML vs text on
script made a difference but that doesn't appear to be true in my testing.

I'm not including test for this because testacular doesn't currently
run tests in xhtml yet.

Closes #1301
2012-08-30 10:53:23 -07:00
Igor Minar 8693eac417 chore(docs): correctly link docs images 2012-08-30 02:26:35 -07:00
Igor Minar e0184d4aef chore(Rakefile): fix the default task 2012-08-29 16:56:48 -07:00
Igor Minar 1702e49548 chore(Rakefile): remove bogus symlink from build 2012-08-29 14:58:10 -07:00
Igor Minar d6706efe7f chore(docs): use symlinks to build docs
so that we can just edit source files without rebuilding docs.

this works for all docs files, except for those that are generated
or rewritten during build.
2012-08-28 16:06:50 -07:00
Igor Minar b08d4b22d2 chore(Rakefile): various build script changes
- restructure rake tasks

  this splits up the concatination and minification into two
  tasks so that we can just build angular.js quickly without wasting
  time with minification which is often not needed when just debugging
  some issue on 3rd party site.

- use symlinks when creating final zip file

- switch from btar to zip

- get rid of version numbers from filenames

- rewrite version numbers in all index files

Closes #1226
2012-08-28 12:38:34 -07:00
Misko Hevery e8ded01cf5 doc($log): correct non-working example 2012-08-27 15:44:38 -07:00
Misko Hevery 7a5f25f667 doc(guide): add concepts 2012-08-27 15:44:38 -07:00
Misko Hevery 96697f464f fix(ngdoc): failing test 2012-08-27 15:44:38 -07:00
Colin Frei 7e18724dfa doc(directive) correct typos 2012-08-27 15:01:50 -07:00
Misko Hevery c269eb3d26 fix(docs) typo 2012-08-27 14:59:19 -07:00
Misko Hevery fa62ea810f fix(ng-list): remove data bound flicker 2012-08-27 14:59:18 -07:00
Misko Hevery bf8ed8a532 doc(misc) updated getting started to reflect the new homepage 2012-08-27 14:59:18 -07:00
Misko Hevery d05a2809a1 doc(guide) simplify the guide home page 2012-08-27 14:59:17 -07:00
Igor Minar fa6c8c3131 chore(Rakefile): rewrite version numbers in all index files 2012-08-27 12:26:04 -07:00
Igor Minar f7ac8ef97a chore(docs): support _escaped_fragment_ hack for crawler 2012-08-25 02:30:55 -07:00
Igor Minar 4a4b28dbf3 chore(docs): use GAE and Google CDN for docs
Short summary: if you use local node server everything should work as before,
if you use GAE, everything should work now as well, but we pull assets from CDN.

- GAE doesn't support ':' in filenames, so I had to replace it with '_'
  but only in the filename, all servers were reconfigured to rewrite the
  urls from : to _ when doing file lookup
- We now pull angular assets from google CDN when deployed on GAE (locally
  or in production). When running on a non GAE server we pull assets from
  ../ directory as before
- Since only certain versions of Angular are available on CDN and we want
  to be able to autodeploy docs, I had to pin down the Angular files
  to a "stable" version when running on GAE
2012-08-24 14:54:35 -07:00
Igor Minar 3e12bc481d docs(a): expose hidden docs
It seems that docs for these directive were previously hidden by accident
2012-08-24 14:54:34 -07:00
johnlindquist 32137cab82 docs(ngRoute): fix typo
aftre -> after
2012-08-23 15:11:07 -04:00
phil f7b4296c38 docs(tutorial): fix typo in step_00
Just removed an extra comma. No big deal.
2012-08-23 01:02:28 -07:00
Igor Minar cab5e1d9b3 fix(docs): update docs top menu links 2012-08-16 11:26:36 -07:00
Igor Minar dfe99836cd fix($compile): denormalize directive templates
Since developers are allowed to customize start/end interpolation
strings, but third-party directive creators don't know about these
customizations, we should standardize on {{ }} in templates of
reusable (third-party) directives. During the compilation, these
templates are then denormalized to use whatever the custom
start/end symbol is, effectively translating the template into the
syntax of the runtime environment.

This addresses an issue raised at http://goo.gl/e8VPV

Existing code should not be affected by this change since project
that do use custom interpolation markers are not expected to use
{{ }} in existing directive templates.
2012-08-13 14:33:56 -07:00
Igor Minar 0f37194fb7 refactor($compile): code cleanup 2012-08-13 09:48:23 -07:00
Brian Ford e85774f709 fix(ngPluralize): fixes ng-pluralize when using non-standard start/end symbols
Closes #1134
2012-08-13 09:48:23 -07:00
Igor Minar 44345c74de style(ngPluralizeSpec): fix indentation 2012-08-13 09:48:22 -07:00
Igor Minar 58f121a5c2 feat($interpolate): expose start/end symbols in run phase
previously the startSymbol() and endSymbol() getters were exposed only via provider
in the config phase
2012-08-13 09:48:22 -07:00
Igor Minar cf6023ef22 docs($interpolateProvider): fixing docs 2012-08-13 09:48:22 -07:00
Igor Minar 2034871764 fix($interpolate): $interpolateProvider.endSymbol() returns startSymbol
I also added missing tests.
2012-08-13 09:48:21 -07:00
Igor Minar 15d283b114 docs($interpolate): fix typo in description 2012-08-13 09:48:21 -07:00
Vojta Jina 9be169365c docs($compileProvider): remove duplicate of .directive() 2012-08-12 10:45:14 -07:00
Vojta Jina 00683a8bbb docs: fix broken links to $compileProvider.directive() 2012-08-12 10:44:29 -07:00
Brian Ford f00b6cca02 fix(docs): fixed documentation for using linky 2012-08-10 16:33:25 -07:00
Brian Ford e05a97c6f5 chore(ngDoc): add support for custom @usage metadata 2012-08-10 16:33:13 -07:00
Brian Ford 2e3651686c fix(docs): added note about using JSON3 as a polyfill for IE7 2012-08-10 16:27:44 -07:00
Brian Ford 536de14821 fix(docs): added note about needing JSON shim for IE7 and earlier 2012-08-10 16:27:44 -07:00
Vojta Jina e0a54f6b20 feat($http): support reponseType
Closes #1013
2012-08-10 16:17:59 -07:00
Igor Minar 9767f7bdd3 fix(option): support option elements in datalist
previously we expected to find option elements only within select element and if
that was not the case we throw an error. This made it impossible to include datalist
element with nested option elements in the template.

Closes #1165
2012-08-10 16:14:30 -07:00
Vojta Jina 167aa0c29c feat($sniffer): auto detect CSP mode
Chrome Canary now has CSP with apis that allow auto-detection. This change
will turn on CSP mode automatically when we detect its presence.

https://dvcs.w3.org/hg/content-security-policy/raw-file/tip/csp-specification.dev.html#script-interfaces--experimental
2012-08-10 14:53:53 -07:00
unirgy 4ccd9eb883 docs($rootScope): fix $on listener signature doc
Added args in $on() listener syntax declaration
2012-08-10 14:50:22 -07:00
Igor Minar c0d638a94b test(jqLite): add missing test for $destroy event 2012-08-10 13:04:39 -07:00
Igor Minar 054d40f338 fix(form): prevent page reload when form destroyed
this fix ensures that we prevent the default action on form submission
(full page reload) even in cases when the form is being destroyed as
a result of the submit event handler (e.g. when route change is
triggered).

The fix is more complicated than I'd like it to be mainly because
we need to ensure that we don't create circular references between
js closures and dom elements via DOM event handlers that would then
result in a memory leak.

Also the differences between IE8, IE9 and normal browsers make testing
this ugly.

Closes #1238
2012-08-10 13:03:55 -07:00
Igor Minar 5cec32492c test(form): fix broken preventDefault test
the original test relied on incorrect assumptions about how jasmine async
tests work (when setTimeout is triggered) and how browser reloads a page
(the sequence of events) and thus the test passes even when the default
is not prevented.

this change fixes the test by registering an extra submit event handler
that checks if the default was prevented.

if the default was not prevented, the test will fail and the page will
be reloaded causing the test runner to panic.
2012-08-07 22:07:49 -07:00
Igor Minar c25cb7d488 refactor(formSpec): group preventDefault specs into a describe 2012-08-07 17:23:16 -07:00
Igor Minar 54e4a6ffbf docs(faq): update faq docs 2012-08-07 10:15:54 -07:00
Igor Minar eee9a51fad docs(styles): fix the cog icon alignment 2012-08-06 16:54:18 -07:00
Vojta Jina 77e6d833f6 chore(nodeserver): add font mime type 2012-08-04 12:09:28 -07:00
Vojta Jina 33ad2b4126 docs(guide): hide scenario for directive example
scenario test for this example would be tricky, we need to teach
the runner how to inject mocks first.
2012-07-30 21:21:34 -07:00
Vojta Jina b84eaffd39 docs: fix icons
Copy fontawesome during build
2012-07-30 21:20:28 -07:00
brettcannon a1107e81eb fix(docs): "in depth" -> "in-depth" 2012-07-20 20:54:42 -07:00
JP Sugarbroad e3e8813e3c refactor($injector): move $injector into the providerCache
Better than special-casing '$injector' in createInjector.
2012-07-19 21:56:22 -07:00
Igor Minar 6e2d9711e8 chore(release): start 1.1.0 increase-gravatas iteration 2012-07-19 21:48:58 -07:00
148 changed files with 5900 additions and 5126 deletions
-10
View File
@@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="org.eclipse.ui.externaltools.ProgramBuilderLaunchConfigurationType">
<booleanAttribute key="org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND" value="false"/>
<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_BUILDER_ENABLED" value="true"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_BUILD_SCOPE" value="${working_set:&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&#10;&lt;launchConfigurationWorkingSet editPageId=&quot;org.eclipse.ui.resourceWorkingSetPage&quot; factoryID=&quot;org.eclipse.ui.internal.WorkingSetFactory&quot; id=&quot;1262905463390_2&quot; label=&quot;workingSet&quot; name=&quot;workingSet&quot;&gt;&#10;&lt;item factoryID=&quot;org.eclipse.ui.internal.model.ResourceFactory&quot; path=&quot;/angular.js/test&quot; type=&quot;2&quot;/&gt;&#10;&lt;item factoryID=&quot;org.eclipse.ui.internal.model.ResourceFactory&quot; path=&quot;/angular.js/src&quot; type=&quot;2&quot;/&gt;&#10;&lt;/launchConfigurationWorkingSet&gt;}"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:/angular.js}/test.sh"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_RUN_BUILD_KINDS" value="full,incremental,auto,"/>
<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_TRIGGERS_CONFIGURED" value="true"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:/angular.js}"/>
</launchConfiguration>
-10
View File
@@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="org.eclipse.ui.externaltools.ProgramBuilderLaunchConfigurationType">
<booleanAttribute key="org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND" value="false"/>
<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_BUILDER_ENABLED" value="false"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_BUILD_SCOPE" value="${working_set:&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&#10;&lt;resources&gt;&#10;&lt;item path=&quot;/angular.js/perf&quot; type=&quot;2&quot;/&gt;&#10;&lt;item path=&quot;/angular.js/src&quot; type=&quot;2&quot;/&gt;&#10;&lt;/resources&gt;}"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:/angular.js/perf.sh}"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_RUN_BUILD_KINDS" value="full,incremental,auto,"/>
<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_TRIGGERS_CONFIGURED" value="true"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:/angular.js}"/>
</launchConfiguration>
-11
View File
@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="org.eclipse.ui.externaltools.ProgramBuilderLaunchConfigurationType">
<stringAttribute key="org.eclipse.debug.core.ATTR_REFRESH_SCOPE" value="${working_set:&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&#10;&lt;resources&gt;&#10;&lt;item path=&quot;/angular.js/build&quot; type=&quot;2&quot;/&gt;&#10;&lt;/resources&gt;}"/>
<booleanAttribute key="org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND" value="false"/>
<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_BUILDER_ENABLED" value="true"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_BUILD_SCOPE" value="${working_set:&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&#10;&lt;resources&gt;&#10;&lt;item path=&quot;/angular.js/docs&quot; type=&quot;2&quot;/&gt;&#10;&lt;item path=&quot;/angular.js/src&quot; type=&quot;2&quot;/&gt;&#10;&lt;/resources&gt;}"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:/angular.js/gen_docs.sh}"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_RUN_BUILD_KINDS" value="full,incremental,auto,"/>
<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_TRIGGERS_CONFIGURED" value="true"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:/angular.js}"/>
</launchConfiguration>
-7
View File
@@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="org.eclipse.ui.externaltools.ProgramLaunchConfigurationType">
<stringAttribute key="org.eclipse.debug.core.ATTR_REFRESH_SCOPE" value="${working_set:&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&#10;&lt;resources&gt;&#10;&lt;item path=&quot;/angular.js/docs&quot; type=&quot;2&quot;/&gt;&#10;&lt;/resources&gt;}"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LAUNCH_CONFIGURATION_BUILD_SCOPE" value="${none}"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:/angular.js/gen_docs.sh}"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:/angular.js}"/>
</launchConfiguration>
-6
View File
@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="org.eclipse.ui.externaltools.ProgramLaunchConfigurationType">
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:/angular.js/lib/jsl/jsl}"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="-conf lib/jsl/jsl.default.conf"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:/angular.js}"/>
</launchConfiguration>
-14
View File
@@ -1,14 +0,0 @@
# Auto detect text files and perform LF normalization
* text=auto
# Standard to msysgit
*.doc diff=astextplain
*.DOC diff=astextplain
*.docx diff=astextplain
*.DOCX diff=astextplain
*.dot diff=astextplain
*.DOT diff=astextplain
*.pdf diff=astextplain
*.PDF diff=astextplain
*.rtf diff=astextplain
*.RTF diff=astextplain
-47
View File
@@ -1,47 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>angular.js</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.wst.jsdt.core.javascriptValidator</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.ui.externaltools.ExternalToolBuilder</name>
<triggers>auto,full,incremental,</triggers>
<arguments>
<dictionary>
<key>LaunchConfigHandle</key>
<value>&lt;project&gt;/.externalToolBuilders/docs.launch</value>
</dictionary>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.ui.externaltools.ExternalToolBuilder</name>
<triggers>auto,full,incremental,</triggers>
<arguments>
<dictionary>
<key>LaunchConfigHandle</key>
<value>&lt;project&gt;/.externalToolBuilders/JSTD_Tests.launch</value>
</dictionary>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.ui.externaltools.ExternalToolBuilder</name>
<triggers>auto,full,incremental,</triggers>
<arguments>
<dictionary>
<key>LaunchConfigHandle</key>
<value>&lt;project&gt;/.externalToolBuilders/JSTD_perf.launch</value>
</dictionary>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.wst.jsdt.core.jsNature</nature>
</natures>
</projectDescription>
-10
View File
@@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry excluding="test/" kind="src" path="src"/>
<classpathentry excluding="docs-data.js|docs-scenario.js" kind="src" path="docs"/>
<classpathentry excluding="test/" kind="src" path="test"/>
<classpathentry kind="src" path="test/test"/>
<classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.JRE_CONTAINER"/>
<classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.baseBrowserLibrary"/>
<classpathentry kind="output" path=""/>
</classpath>
@@ -1,16 +0,0 @@
#Mon Jan 24 10:31:47 PST 2011
activeContentFilterList=*.makefile,makefile,*.Makefile,Makefile,Makefile.*,*.mk,MANIFEST.MF
addNewLine=true
convertActionOnSaave=AnyEdit.CnvrtTabToSpaces
eclipse.preferences.version=1
inActiveContentFilterList=
javaTabWidthForJava=true
org.eclipse.jdt.ui.editor.tab.width=2
projectPropsEnabled=false
removeTrailingSpaces=true
replaceAllSpaces=false
replaceAllTabs=false
saveAndAddLine=true
saveAndConvert=true
saveAndTrim=true
useModulo4Tabs=false
@@ -1 +0,0 @@
org.eclipse.wst.jsdt.launching.JRE_CONTAINER
@@ -1 +0,0 @@
Global
+120 -1
View File
@@ -1,8 +1,127 @@
<a name="1.1.2"></a>
# 1.1.2 tofu-animation (2013-01-22)
_Note: 1.1.x releases are [considered unstable](http://blog.angularjs.org/2012/07/angularjs-10-12-roadmap.html).
They pass all tests but we reserve the right to change new features/apis in between minor releases. Check them
out and please give us feedback._
_Note: This release also contains all bug fixes available in [1.0.4](#1.0.4)._
## Features
- **$compile:** support modifying the DOM structure in postlink fn
([cdf6fb19](https://github.com/angular/angular.js/commit/cdf6fb19c85560b30607e71dc2b19fde54760faa))
- **$log:** add $log.debug()
([9e991ddb](https://github.com/angular/angular.js/commit/9e991ddb1de13adf520eda459950be5b90b5b6d9),
[#1592](https://github.com/angular/angular.js/issues/1592))
- **$parse:** allow strict equality in angular expressions
([a179a9a9](https://github.com/angular/angular.js/commit/a179a9a96eda5c566bda8a70ac8a75822c936a68),
[#908](https://github.com/angular/angular.js/issues/908))
- **$resource:**
- allow dynamic default parameters
([cc42c99b](https://github.com/angular/angular.js/commit/cc42c99bec6a03d6c41b8e1d29ba2b1f5c16b87d))
- support all $http.config actions
([af89daf4](https://github.com/angular/angular.js/commit/af89daf4641f57b92be6c1f3635f5a3237f20c71))
- **$route:** allow using functions as template params in 'when'
([faf02f0c](https://github.com/angular/angular.js/commit/faf02f0c4db7962f863b0da2a82c8cafab2c706f))
- **$timeout-mock:** add verifyNoPendingTasks method
([f0c6ebc0](https://github.com/angular/angular.js/commit/f0c6ebc07653f6267acec898ccef5677884e3081),
[#1245](https://github.com/angular/angular.js/issues/1245))
- **directive:**
- added ngOpen boolean directive
([b8bd4d54](https://github.com/angular/angular.js/commit/b8bd4d5460d9952e9a3bb14992636b17859bd457))
- ngKeydown, ngKeyup
([e03182f0](https://github.com/angular/angular.js/commit/e03182f018f5069acd5e883ce2e9349b83f2d03f),
[#1035](https://github.com/angular/angular.js/issues/1035))
- **limitTo filter:** limitTo filter accepts strings
([9e96d983](https://github.com/angular/angular.js/commit/9e96d983451899ef0cef3e68395c8f6c1ef83bbe),
[#653](https://github.com/angular/angular.js/issues/653))
- **scenario:**
- add mouseover method to the ngScenario dsl
([2f437e89](https://github.com/angular/angular.js/commit/2f437e89781cb2b449abb685e36b26ca1cf0fff5))
- fail when an option to select does not exist
([15183f3e](https://github.com/angular/angular.js/commit/15183f3e1fbee031c9595206163962788f98b298))
## Breaking Changes
- **date:** due to [cc821502](https://github.com/angular/angular.js/commit/cc821502bca64d15e1c576bf20a62b28b3d9a88a),
string input without timezone info is now parsed as local time/date
<a name="1.0.4"></a>
# 1.0.4 bewildering-hair (2013-01-22)
## Bug Fixes
- **$compile:**
- do not wrap empty root text nodes in spans
([49f9e4ce](https://github.com/angular/angular.js/commit/49f9e4cef13e68ff85b3c160cf8fac6e7cd042a3),
[#1059](https://github.com/angular/angular.js/issues/1059))
- safely create transclude comment nodes
([74dd2f79](https://github.com/angular/angular.js/commit/74dd2f7980ea8ec434a6e0565d857c910653ed9b),
[#1740](https://github.com/angular/angular.js/issues/1740))
- **$injector:**
- remove bogus fn arg
([b6b7c5a1](https://github.com/angular/angular.js/commit/b6b7c5a1d66073937709158da8c2d688cb45c9f6),
[#1711](https://github.com/angular/angular.js/issues/1711))
- provider can now be defined in the array format
([2c405f41](https://github.com/angular/angular.js/commit/2c405f417125c80c387a51baece8bf6e1e0c0a81),
[#1452](https://github.com/angular/angular.js/issues/1452))
- **$resource:**
- HTTP method should be case-insensitive
([8991680d](https://github.com/angular/angular.js/commit/8991680d8ab632dda60cd70c780868c803c74509),
[#1403](https://github.com/angular/angular.js/issues/1403))
- **$route:**
- support route params not separated with slashes.
([c6392616](https://github.com/angular/angular.js/commit/c6392616ea5245bd0d2f77dded0b948d9e2637c8))
- correctly extract $routeParams from urls
([30a9da5d](https://github.com/angular/angular.js/commit/30a9da5dc159dd1e19b677914356925c7ebdf632))
- **Scope:** ensure that a scope is destroyed only once
([d6da505f](https://github.com/angular/angular.js/commit/d6da505f4e044f8a487ac27a3ec707c11853ee0a),
[#1627](https://github.com/angular/angular.js/issues/1627))
- **angular.equals:**
- consistently compare undefined object props
([5ae63fd3](https://github.com/angular/angular.js/commit/5ae63fd385295d5a7bbdc79466f59727dcab1c85),
[3c2e1c5e](https://github.com/angular/angular.js/commit/3c2e1c5e4d12529b1d69a6173c38097527dccc4f),
[#1648](https://github.com/angular/angular.js/issues/1648))
- **date filter:** parse string input as local time unless TZ is specified
([cc821502](https://github.com/angular/angular.js/commit/cc821502bca64d15e1c576bf20a62b28b3d9a88a),
[#847](https://github.com/angular/angular.js/issues/847))
- **jqLite:**
- children() should only return elements
([febb4c1c](https://github.com/angular/angular.js/commit/febb4c1c35cf767ae31fc9fef1f4b4f026ac9de0))
- make next() ignore non-element nodes
([76a6047a](https://github.com/angular/angular.js/commit/76a6047af690781b8238ba7924279470ba76d081))
- **scenario:** don't trigger input events on IE9
([8b9e6c35](https://github.com/angular/angular.js/commit/8b9e6c3501746edb2c9e2d585e8e0eaeb8ba8327))
- **Directives:**
- **ngRepeat:** correctly apply $last if repeating over object
([7e746015](https://github.com/angular/angular.js/commit/7e746015ea7dec3e9eb81bc4678fa9b6a83bc47c),
[#1789](https://github.com/angular/angular.js/issues/1789))
- **ngResource:** correct leading slash removal.
([b2f46251](https://github.com/angular/angular.js/commit/b2f46251aca76c8568ee7d4bab54edbc9d7a186a))
- **ngSwitch:** don't leak when destroyed while not attached
([a26234f7](https://github.com/angular/angular.js/commit/a26234f7183013e2fcc9b35377e181ad96dc9917),
[#1621](https://github.com/angular/angular.js/issues/1621))
- **select:** support optgroup + select[multiple] combo
([26adeb11](https://github.com/angular/angular.js/commit/26adeb119bc4fafa6286de484626b8de4170abc9),
[#1553](https://github.com/angular/angular.js/issues/1553))
## Features
- **$compile:** support modifying the DOM structure in postlink fn
([cdf6fb19](https://github.com/angular/angular.js/commit/cdf6fb19c85560b30607e71dc2b19fde54760faa))
<a name="1.1.1"></a>
# 1.1.1 pathological-kerning (2012-11-26)
_Note: 1.1.x releases are [considered unstable](http://blog.angularjs.org/2012/07/angularjs-10-12-roadmap.html).
They pass all tests but we reseve the right to change new features/apis in between minor releases. Check them
They pass all tests but we reserve the right to change new features/apis in between minor releases. Check them
out and please give us feedback._
_Note: This release also contains all bug fixes available in [1.0.3](#1.0.3)._
+3 -3
View File
@@ -1,11 +1,11 @@
AngularJS
=========
AngularJS lets you write client-side web applications as if you had a smarter browser. It lets use
good old HTML (or HAML, Jade and friends!) as your template language and lets you extend HTMLs
AngularJS lets you write client-side web applications as if you had a smarter browser. It lets you
use good old HTML (or HAML, Jade and friends!) as your template language and lets you extend HTMLs
syntax to express your applications components clearly and succinctly. It automatically
synchronizes data from your UI (view) with your JavaScript objects (model) through 2-way data
binding. To help you structure your application better and make it easy to test AngularJS teaches
binding. To help you structure your application better and make it easy to test, AngularJS teaches
the browser how to do dependency injection and inversion of control. Oh yeah and it also helps with
server-side communication, taming async callbacks with promises and deferreds; and make client-side
navigation and deeplinking with hashbang urls or HTML5 pushState a piece of cake. The best of all:
+23 -24
View File
@@ -57,25 +57,6 @@ task :concat_scenario => :init do
end
desc 'Concat JSTD Scenario Adapter'
task :concat_jstd_scenario_adapter => :init do
concat_file('jstd-scenario-adapter.js', [
'src/ngScenario/jstd-scenario-adapter/angular.prefix',
'src/ngScenario/jstd-scenario-adapter/Adapter.js',
'src/ngScenario/jstd-scenario-adapter/angular.suffix',
])
# TODO(vojta) use jstd configuration when implemented
# (instead of including jstd-adapter-config.js)
File.open(path_to('jstd-scenario-adapter-config.js'), 'w') do |f|
f.write("/**\r\n" +
" * Configuration for jstd scenario adapter \n */\n" +
"var jstdScenarioAdapter = {\n relativeUrlPrefix: '/build/docs/'\n};\n")
end
end
desc 'Concat AngularJS files'
task :concat => :init do
@@ -115,7 +96,7 @@ end
desc 'Minify JavaScript'
task :minify => [:init, :concat, :concat_scenario, :concat_jstd_scenario_adapter] do
task :minify => [:init, :concat, :concat_scenario] do
[ 'angular.js',
'angular-cookies.js',
'angular-loader.js',
@@ -124,16 +105,26 @@ task :minify => [:init, :concat, :concat_scenario, :concat_jstd_scenario_adapter
'angular-bootstrap.js',
'angular-bootstrap-prettify.js'
].each do |file|
fork { closure_compile(file) }
unless ENV['TRAVIS']
fork { closure_compile(file) }
else
closure_compile(file)
end
end
Process.waitall
end
desc 'Generate version.txt file'
desc 'Generate version.txt and version.json files'
task :version => [:init] do
`echo #{NG_VERSION.full} > #{path_to('version.txt')}`
`echo '{
"full": "#{NG_VERSION.full}",
"major": "#{NG_VERSION.major}",
"minor": "#{NG_VERSION.minor}",
"dot": "#{NG_VERSION.dot}",
"codename": "#{NG_VERSION.codename}"\n}' > #{path_to('version.json')}`
end
@@ -286,14 +277,22 @@ def path_to(filename)
end
##
# returns the 32-bit mode force flags for java compiler if supported, this makes the build much
# faster
#
def java32flags
return '-d32 -client' unless Rake::Win32.windows? || `java -version -d32 2>&1`.match(/Error/i)
end
def closure_compile(filename)
puts "Minifying #{filename} ..."
min_path = path_to(filename.gsub(/\.js$/, '.min.js'))
%x(java \
-client \
-d32 \
#{java32flags()} \
-jar lib/closure-compiler/compiler.jar \
--compilation_level SIMPLE_OPTIMIZATIONS \
--language_in ECMASCRIPT5_STRICT \
-1
View File
@@ -79,7 +79,6 @@ angularFiles = {
'src/ngScenario/Describe.js',
'src/ngScenario/Future.js',
'src/ngScenario/ObjectModel.js',
'src/ngScenario/Describe.js',
'src/ngScenario/Runner.js',
'src/ngScenario/SpecRunner.js',
'src/ngScenario/dsl.js',
+27 -22
View File
@@ -36,16 +36,15 @@ var parseRawCommit = function(raw) {
msg.breaks = [];
lines.forEach(function(line) {
match = line.match(/Closes\s#(\d+)/);
match = line.match(/(?:Closes|Fixes)\s#(\d+)/);
if (match) msg.closes.push(parseInt(match[1]));
});
match = raw.match(/BREAKING CHANGE:([\s\S]*)/);
if (match) {
console.log('found!!!')
msg.breaks.push(match[1]);
msg.breaking = match[1];
}
msg.body = lines.join('\n');
match = msg.subject.match(/^(.*)\((.*)\)\:\s(.*)$/);
@@ -88,7 +87,8 @@ var currentDate = function() {
};
var printSection = function(stream, title, section) {
var printSection = function(stream, title, section, printCommitLinks) {
printCommitLinks = printCommitLinks === undefined ? true : printCommitLinks;
var components = Object.getOwnPropertyNames(section).sort();
if (!components.length) return;
@@ -109,11 +109,15 @@ var printSection = function(stream, title, section) {
}
section[name].forEach(function(commit) {
stream.write(util.format('%s %s (%s', prefix, commit.subject, linkToCommit(commit.hash)));
if (commit.closes.length) {
stream.write(', closes ' + commit.closes.map(linkToIssue).join(', '));
if (printCommitLinks) {
stream.write(util.format('%s %s\n (%s', prefix, commit.subject, linkToCommit(commit.hash)));
if (commit.closes.length) {
stream.write(',\n ' + commit.closes.map(linkToIssue).join(', '));
}
stream.write(')\n');
} else {
stream.write(util.format('%s %s', prefix, commit.subject));
}
stream.write(')\n');
});
});
@@ -122,7 +126,7 @@ var printSection = function(stream, title, section) {
var readGitLog = function(grep, from) {
var deffered = q.defer();
var deferred = q.defer();
// TODO(vojta): if it's slow, use spawn and stream it instead
child.exec(util.format(GIT_LOG_CMD, grep, '%H%n%s%n%b%n==END==', from), function(code, stdout, stderr) {
@@ -133,10 +137,10 @@ var readGitLog = function(grep, from) {
if (commit) commits.push(commit);
});
deffered.resolve(commits);
deferred.resolve(commits);
});
return deffered.promise;
return deferred.promise;
};
@@ -158,29 +162,30 @@ var writeChangelog = function(stream, commits, version) {
section[component].push(commit);
}
commit.breaks.forEach(function(breakMsg) {
sections.breaks[EMPTY_COMPONENT].push({
subject: breakMsg,
if (commit.breaking) {
sections.breaks[component] = sections.breaks[component] || [];
sections.breaks[component].push({
subject: util.format("due to %s,\n %s", linkToCommit(commit.hash), commit.breaking),
hash: commit.hash,
closes: []
});
});
};
});
stream.write(util.format(HEADER_TPL, version, version, currentDate()));
printSection(stream, 'Bug Fixes', sections.fix);
printSection(stream, 'Features', sections.feat);
printSection(stream, 'Breaking Changes', sections.breaks);
printSection(stream, 'Breaking Changes', sections.breaks, false);
}
var getPreviousTag = function() {
var deffered = q.defer();
var deferred = q.defer();
child.exec(GIT_TAG_CMD, function(code, stdout, stderr) {
if (code) deffered.reject('Cannot get the previous tag.');
else deffered.resolve(stdout.replace('\n', ''));
if (code) deferred.reject('Cannot get the previous tag.');
else deferred.resolve(stdout.replace('\n', ''));
});
return deffered.promise;
return deferred.promise;
};
+3 -3
View File
@@ -34,10 +34,10 @@ describe('changelog.js', function() {
'13f31602f396bc269076ab4d389cfd8ca94b20ba\n' +
'feat(ng-list): Allow custom separator\n' +
'bla bla bla\n\n' +
'Breaks first breaking change\nsomething else\n' +
'Breaks another breaking change\n');
'BREAKING CHANGE: first breaking change\nsomething else\n' +
'another line with more info\n');
expect(msg.breaks).toEqual(['first breaking change', 'another breaking change']);
expect(msg.breaking).toEqual(' first breaking change\nsomething else\nanother line with more info\n');
});
});
});
+6 -6
View File
@@ -3,7 +3,7 @@
@description
External resources are URLs that provide JSON data, which are then rendered with the help of
templates. angular has a resource factory that can be used to give names to the URLs and then
templates. Angular has a resource factory that can be used to give names to the URLs and then
attach behavior to them. For example you can use the
{@link http://code.google.com/apis/buzz/v1/getting_started.html#background-operations| Google Buzz
API}
@@ -21,12 +21,12 @@ to retrieve Buzz activity and comments.
{ get: {method: 'JSONP', params: {visibility: '@self'}},
replies: {method: 'JSONP', params: {visibility: '@self', comments: '@comments'}}
});
}
BuzzController.prototype = {
fetch: function() {
$scope.fetch = function() {
$scope.activities = $scope.Activity.get({userId:this.userId});
},
expandReplies: function(activity) {
}
$scope.expandReplies = function(activity) {
activity.replies = $scope.Activity.replies({userId: this.userId, activityId: activity.id});
}
};
+1 -1
View File
@@ -5,7 +5,7 @@
Deep linking allows you to encode the state of the application in the URL so that it can be
bookmarked and the application can be restored from the URL to the same state.
While angular does not force you to deal with bookmarks in any particular way, it has services
While Angular does not force you to deal with bookmarks in any particular way, it has services
which make the common case described here very easy to implement.
# Assumptions
+1 -1
View File
@@ -2,7 +2,7 @@
@name Cookbook: Form
@description
A web application's main purpose is to present and gather data. For this reason angular strives
A web application's main purpose is to present and gather data. For this reason Angular strives
to make both of these operations trivial. This example shows off how you can build a simple form to
allow a user to enter data.
+2 -2
View File
@@ -28,10 +28,10 @@
Take a look through the source and note:
* The script tag that {@link guide/bootstrap bootstraps} the angular environment.
* The script tag that {@link guide/bootstrap bootstraps} the Angular environment.
* The text {@link api/ng.directive:input input form control} which is
bound to the greeting name text.
* No need for listener registration and event firing on change events.
* There is no need for listener registration and event firing on change events.
* The implicit presence of the `name` variable which is in the root {@link api/ng.$rootScope.Scope scope}.
* The double curly brace `{{markup}}`, which binds the name variable to the greeting text.
* The concept of {@link guide/dev_guide.templates.databinding data binding}, which reflects any
+3 -3
View File
@@ -2,7 +2,7 @@
@name Cookbook
@description
Welcome to the angular cookbook. Here we will show you typical uses of angular by example.
Welcome to the Angular cookbook. Here we will show you typical uses of Angular by example.
# Hello World
@@ -45,7 +45,7 @@ allowing you to send links to specific screens in your app.
# Services
{@link api/ng Services}: Services are long lived objects in your applications that are
available across controllers. A collection of useful services are pre-bundled with angular but you
available across controllers. A collection of useful services are pre-bundled with Angular but you
will likely add your own. Services are initialized using dependency injection, which resolves the
order of initialization. This safeguards you from the perils of global state (a common way to
implement long lived objects).
@@ -55,4 +55,4 @@ implement long lived objects).
{@link buzz Resources}: Web applications must be able to communicate with the external
services to get and update data. Resources are the abstractions of external URLs which are
specially tailored to angular data binding.
specially tailored to Angular data binding.
+2 -2
View File
@@ -2,7 +2,7 @@
@name Cookbook: MVC
@description
MVC allows for a clean an testable separation between the behavior (controller) and the view
MVC allows for a clean and testable separation between the behavior (controller) and the view
(HTML template). A Controller is just a JavaScript class which is grafted onto the scope of the
view. This makes it very easy for the controller and the view to share the model.
@@ -115,7 +115,7 @@ view.
# Things to notice
* The controller is defined in JavaScript and has no reference to the rendering logic.
* The controller is instantiated by <angular/> and injected into the view.
* The controller is instantiated by Angular and injected into the view.
* The controller can be instantiated in isolation (without a view) and the code will still execute.
This makes it very testable.
* The HTML view is a projection of the model. In the above example, the model is stored in the
+9 -9
View File
@@ -9,7 +9,7 @@ browser new HTML syntax. The compiler allows you to attach behavior to any HTML
and even create new HTML element or attributes with custom behavior. Angular calls these behavior
extensions {@link api/ng.$compileProvider#directive directives}.
HTML has a lot of constructs for formatting the HTML for static documents in declarative fashion.
HTML has a lot of constructs for formatting the HTML for static documents in a declarative fashion.
For example if something needs to be centered, there is no need to provide instructions to the
browser how the window size needs to be divided in half so that center is found, and that this
center needs to be aligned with the text's center. Simply add `align="center"` attribute to any
@@ -37,7 +37,7 @@ process happens into two phases.
2. **Link:** combine the directives with a scope and produce a live view. Any changes in the
scope model are reflected in the view, and any user interactions with the view are reflected
in the scope model. Making the scope model a single source of truth.
in the scope model. This makes the scope model the single source of truth.
Some directives such {@link api/ng.directive:ngRepeat
`ng-repeat`} clone DOM elements once for each item in collection. Having a compile and link phase
@@ -47,9 +47,9 @@ once for each clone instance.
# Directive
Directive is a behavior which should be triggered when specific HTML constructs are encountered in
compilation process. The directives can be placed in element names, attributes, class names, as
well as comments. Here are some equivalent examples of invoking {@link
A directive is a behavior which should be triggered when specific HTML constructs are encountered in
the compilation process. The directives can be placed in element names, attributes, class names, as
well as comments. Here are some equivalent examples of invoking the {@link
api/ng.directive:ngBind `ng-bind`} directive.
<pre>
@@ -59,7 +59,7 @@ api/ng.directive:ngBind `ng-bind`} directive.
<!-- directive: ng-bind exp -->
</pre>
Directive is just a function which executes when the compiler encounters it in the DOM. See {@link
A directive is just a function which executes when the compiler encounters it in the DOM. See {@link
api/ng.$compileProvider#directive directive API} for in-depth documentation on how
to write directives.
@@ -107,9 +107,9 @@ Here is a directive which makes any element draggable. Notice the `draggable` at
</example>
The presence of `draggable` attribute on any element gives the element new behavior. The beauty of
The presence of the `draggable` attribute on any element gives the element new behavior. The beauty of
this approach is that we have taught the browser a new trick. We have extended the vocabulary of
what the browser understands in a way, which is natural to anyone who is familiar with HTML
what the browser understands in a way which is natural to anyone who is familiar with HTML
principles.
@@ -122,7 +122,7 @@ an element.
<img src="img/One_Way_Data_Binding.png">
This means that any changes to the data need to be re-merged with the template and then
`innerHTML`ed into the DOM. Some of the issues are: reading user input and merging it with data,
`innerHTML`ed into the DOM. Some of the issues with this approach are: reading user input and merging it with data,
clobbering user input by overwriting it, managing the whole update process, and lack of behavior
expressiveness.
+29 -29
View File
@@ -26,20 +26,20 @@ This is how we get the ball rolling (refer to the diagram and example below):
<img class="pull-right" style="padding-left: 3em;" src="img/guide/concepts-startup.png">
1. Browser loads the HTML and parses it into a DOM
2. Browser loads `angular.js` script
1. The browser loads the HTML and parses it into a DOM
2. The browser loads `angular.js` script
3. Angular waits for `DOMContentLoaded` event
4. Angular looks for {@link api/ng.directive:ngApp ng-app}
{@link guide/directive directive}, which designates application boundary
5. {@link guide/module Module} specified in {@link
{@link guide/directive directive}, which designates the application boundary
5. The {@link guide/module Module} specified in {@link
api/ng.directive:ngApp ng-app} (if any) is used to configure
the {@link api/AUTO.$injector $injector}
6. {@link api/AUTO.$injector $injector} is used to create the {@link
6. The {@link api/AUTO.$injector $injector} is used to create the {@link
api/ng.$compile $compile} service as well as {@link
api/ng.$rootScope $rootScope}
7. {@link api/ng.$compile $compile} service is used to compile the DOM and link
7. The {@link api/ng.$compile $compile} service is used to compile the DOM and link
it with {@link api/ng.$rootScope $rootScope}
8. {@link api/ng.directive:ngInit ng-init} {@link
8. The {@link api/ng.directive:ngInit ng-init} {@link
guide/directive directive} assigns `World` to the `name` property on the {@link guide/scope
scope}
9. The `{{name}}` {@link api/ng.$interpolate interpolates} the expression to
@@ -59,21 +59,21 @@ This is how we get the ball rolling (refer to the diagram and example below):
<img class="pull-right" style="padding-left: 3em; padding-bottom: 1em;" src="img/guide/concepts-runtime.png">
The diagram and the example below describe how Angular interacts with browser's event loop.
The diagram and the example below describe how Angular interacts with the browser's event loop.
1. Browsers event-loop waits for an event to arrive. Event is a user interactions, timer event,
1. The browser's event-loop waits for an event to arrive. An event is a user interactions, timer event,
or network event (response from a server).
2. The events callback gets executed. This enters the JavaScript context. The callback can
2. The event's callback gets executed. This enters the JavaScript context. The callback can
modify the DOM structure.
3. Once the callback finishes execution, the browser leaves the JavaScript context and
3. Once the callback executes, the browser leaves the JavaScript context and
re-renders the view based on DOM changes.
Angular modifies the normal JavaScript flow by providing it's own event processing loop. This
Angular modifies the normal JavaScript flow by providing its own event processing loop. This
splits the JavaScript into classical and Angular execution context. Only operations which are
applied in Angular execution context will benefit from angular data-binding, exception handling,
property watching, etc... Use $apply() to enter Angular execution context from JavaScript. Keep in
mind that in most places (controllers, services) the $apply has already been called for you by the
directive which is handling the event. The need to call $apply is reserved only when
applied in Angular execution context will benefit from Angular data-binding, exception handling,
property watching, etc... You can also use $apply() to enter Angular execution context from JavaScript. Keep in
mind that in most places (controllers, services) $apply has already been called for you by the
directive which is handling the event. An explicit call to $apply is needed only when
implementing custom event callbacks, or when working with a third-party library callbacks.
1. Enter Angular execution context by calling {@link guide/scope scope}`.`{@link
@@ -89,14 +89,14 @@ implementing custom event callbacks, or when working with a third-party library
$evalAsync} queue is empty and the {@link api/ng.$rootScope.Scope#$watch
$watch} list does not detect any changes.
4. The {@link api/ng.$rootScope.Scope#$evalAsync $evalAsync} queue is used to
schedule work which needs to occur outside of current stack frame, but before the browser
schedule work which needs to occur outside of current stack frame, but before the browser's
view render. This is usually done with `setTimeout(0)`, but the `setTimeout(0)` approach
suffers from slowness and may cause view flickering since the browser renders the view after
each event.
5. The {@link api/ng.$rootScope.Scope#$watch $watch} list is a set of expressions
which may have changed since last iteration. If a change is detected then the `$watch`
function is called which typically updates the DOM with the new value.
6. Once Angular {@link api/ng.$rootScope.Scope#$digest $digest} loop finishes
6. Once the Angular {@link api/ng.$rootScope.Scope#$digest $digest} loop finishes
the execution leaves the Angular and JavaScript context. This is followed by the browser
re-rendering the DOM to reflect any changes.
@@ -188,7 +188,7 @@ a diagram depicting the scope boundaries.
<img class="pull-right" style="padding-left: 3em; padding-bottom: 1em;" src="img/guide/concepts-controller.png">
Controller is the code behind the view. Its job is to construct the model and publish it to the
A controller is the code behind the view. Its job is to construct the model and publish it to the
view along with callback methods. The view is a projection of the scope onto the template (the
HTML). The scope is the glue which marshals the model to the view and forwards the events to the
controller.
@@ -233,7 +233,7 @@ The separation of the controller and the view is important because:
<img class="pull-right" style="padding-left: 3em; padding-bottom: 1em;" src="img/guide/concepts-model.png">
The model is the data which is used merged with the template to produce the view. To be able to
render the model into the view, the model has to be referenceable from the scope. Unlike many
render the model into the view, the model has to be able to be referenced from the scope. Unlike many
other frameworks Angular makes no restrictions or requirements an the model. There are no classes
to inherit from or special accessor methods for accessing or changing the model. The model can be
primitive, object hash, or a full object Type. In short the model is a plain JavaScript object.
@@ -250,7 +250,7 @@ primitive, object hash, or a full object Type. In short the model is a plain Jav
The view is what the users sees. The view begins its life as a template, it is merged with the
model and finally rendered into the browser DOM. Angular takes a very different approach to
rendering the view, to most other templating systems.
rendering the view, compared to most other templating systems.
* **Others** - Most templating systems begin as an HTML string with special templating markup.
Often the template markup breaks the HTML syntax which means that the template can not be
@@ -261,9 +261,9 @@ rendering the view, to most other templating systems.
is the granularity of the DOM updates. The key here is that the templating system manipulates
strings.
* **Angular** - Angular is different, since its templating system works on DOM objects not on
strings. The template is still written in HTML string, but it is HTML (not HTML with
template sprinkled in.) The browser parses the HTML into DOM, and the DOM becomes the input to
the template engine know as the {@link api/ng.$compile compiler}. The compiler
strings. The template is still written in an HTML string, but it is HTML (not HTML with
template sprinkled in.) The browser parses the HTML into the DOM, and the DOM becomes the input to
the template engine known as the {@link api/ng.$compile compiler}. The compiler
looks for {@link guide/directive directives} which in turn set up {@link
api/ng.$rootScope.Scope#$watch watches} on the model. The result is a
continuously updating view which does not need template model re-merging. Your model becomes
@@ -291,7 +291,7 @@ rendering the view, to most other templating systems.
<a name="directives"></a>
# Directives
A directive is a behavior or DOM transformation which is triggered by a presence of an attribute,
A directive is a behavior or DOM transformation which is triggered by the presence of a custom attribute,
element name, or a class name. A directive allows you to extend the HTML vocabulary in a
declarative fashion. Following is an example which enables data-binding for the `contenteditable`
in HTML.
@@ -310,7 +310,7 @@ in HTML.
});
// model -> view
ctrl.render = function(value) {
ctrl.$render = function(value) {
elm.html(value);
};
@@ -337,7 +337,7 @@ in HTML.
<a name="filters"></a>
# Filters
{@link api/ng.$filter Filters} perform data transformation roles. Typically
{@link api/ng.$filter Filters} perform data transformation. Typically
they are used in conjunction with the locale to format the data in locale specific output.
They follow the spirit of UNIX filters and use similar syntax `|` (pipe).
@@ -358,7 +358,7 @@ They follow the spirit of UNIX filters and use similar syntax `|` (pipe).
<img class="pull-right" style="padding-left: 3em; padding-bottom: 1em;" src="img/guide/concepts-module-injector.png">
An {@link api/AUTO.$injector injector} is a service locator. There is a single
The {@link api/AUTO.$injector injector} is a service locator. There is a single
{@link api/AUTO.$injector injector} per Angular {@link
api/ng.directive:ngApp application}. The {@link
api/AUTO.$injector injector} provides a way to look up an object instance by its
@@ -438,7 +438,7 @@ dependencies, look for dependencies, or even get a reference to the injector.
</file>
<file name="script.js">
angular.module('timeExampleModule', []).
// Declare new object call time,
// Declare new object called time,
// which will be available for injection
factory('time', function($timeout) {
var time = {};
@@ -11,7 +11,7 @@ that will help you verify the health of your Angular application.
# Overview
You will write scenario tests in JavaScript, which describe how your application should behave,
given a certain interaction in a specific state. A scenario is comprised of one or more it blocks
given a certain interaction in a specific state. A scenario is comprised of one or more `it` blocks
(you can think of these as the requirements of your application), which in turn are made of
**commands** and **expectations**. Commands tell the Runner to do something with the application
(such as navigate to a page or click on a button), and expectations tell the Runner to assert
@@ -175,4 +175,4 @@ Executes the `method` passing in `key` and `value` on the element matching the g
JavaScript is a dynamically typed language which comes with great power of expression, but it also
come with almost no-help from the compiler. For this reason we feel very strongly that any code
written in JavaScript needs to come with a strong set of tests. We have built many features into
angular which makes testing your angular applications easy. So there is no excuse for not do it.
angular which makes testing your angular applications easy. So there is no excuse for not testing.
+2 -2
View File
@@ -3,11 +3,11 @@
@description
While Model-View-Controller (MVC) has acquired different shades of meaning over the years since it
first appeared, angular incorporates the basic principles behind the original {@link
first appeared, Angular incorporates the basic principles behind the original {@link
http://en.wikipedia.org/wiki/Modelviewcontroller MVC} software design pattern into its way of
building client-side web applications.
The MVC pattern greatly summarized:
The MVC pattern summarized:
* Separate applications into distinct presentation, data, and logic components
* Encourage loose coupling between these components
@@ -2,10 +2,10 @@
@name Developer Guide: About MVC in Angular: Understanding the Controller Component
@description
In angular, a controller is a JavaScript function(type/class) that is used to augment instances of
angular {@link scope Scope}, excluding the root scope. When you or angular create a new
In Angular, a controller is a JavaScript function(type/class) that is used to augment instances of
angular {@link scope Scope}, excluding the root scope. When you or Angular create a new
child scope object via the {@link api/ng.$rootScope.Scope#$new scope.$new} API , there is an
option to pass in a controller as a method argument. This will tell angular to associate the
option to pass in a controller as a method argument. This will tell Angular to associate the
controller with the new scope and to augment its behavior.
Use controllers to:
@@ -15,10 +15,10 @@ Use controllers to:
# Setting up the initial state of a scope object
Typically, when you create an application you need to set up an initial state for an angular scope.
Typically, when you create an application you need to set up an initial state for an Angular scope.
Angular applies (in the sense of JavaScript's `Function#apply`) the controller constructor function
to a new angular scope object, which sets up an initial scope state. This means that angular never
to a new Angular scope object, which sets up an initial scope state. This means that Angular never
creates instances of the controller type (by invoking the `new` operator on the controller
constructor). Constructors are always applied to an existing scope object.
@@ -30,9 +30,23 @@ function GreetingCtrl($scope) {
The `GreetingCtrl` controller creates a `greeting` model which can be referred to in a template.
**NOTE**: Many of the examples in the documentation show the creation of functions
in the global scope. This is only for demonstration purposes - in a real
application you should use the `.controller` method of your Angular module for
your application as follows:
var myApp = angular.module('myApp',[]);
myApp.controller('GreetingCtrl', ['$scope', function(scope) {
scope.greeting = 'Hola!';
}]);
Note also that we use the array notation to explicitly specify the dependency
of the controller on the `$scope` service provided by Angular.
# Adding Behavior to a Scope Object
Behavior on an angular scope object is in the form of scope method properties available to the
Behavior on an Angular scope object is in the form of scope method properties available to the
template/view. This behavior interacts with and modifies the application model.
As discussed in the {@link dev_guide.mvc.understanding_model Model} section of this guide, any
@@ -55,14 +69,14 @@ Do not use controllers for:
- Any kind of DOM manipulation — Controllers should contain only business logic. DOM
manipulation—the presentation logic of an application—is well known for being hard to test.
Putting any presentation logic into controllers significantly affects testability of the business
logic. Angular offers {@link dev_guide.templates.databinding} for automatic DOM manipulation. If
logic. Angular offers {@link dev_guide.templates.databinding databinding} for automatic DOM manipulation. If
you have to perform your own manual DOM manipulation, encapsulate the presentation logic in
{@link guide/directive directives}.
- Input formatting — Use {@link forms angular form controls} instead.
- Output filtering — Use {@link dev_guide.templates.filters angular filters} instead.
- Run stateless or stateful code shared across controllers — Use {@link dev_guide.services angular
- To run stateless or stateful code shared across controllers — Use {@link dev_guide.services angular
services} instead.
- Instantiate or manage the life-cycle of other components (for example, to create service
- To instantiate or manage the life-cycle of other components (for example, to create service
instances).
@@ -157,7 +171,7 @@ input box) in the second button.
## Controller Inheritance Example
Controller inheritance in angular is based on {@link api/ng.$rootScope.Scope Scope} inheritance. Let's
Controller inheritance in Angular is based on {@link api/ng.$rootScope.Scope Scope} inheritance. Let's
have a look at an example:
<pre>
@@ -197,7 +211,7 @@ Inheritance works between controllers in the same way as it does with models. So
examples, all of the models could be replaced with controller methods that return string values.
Note: Standard prototypical inheritance between two controllers doesn't work as one might expect,
because as we mentioned earlier, controllers are not instantiated directly by angular, but rather
because as we mentioned earlier, controllers are not instantiated directly by Angular, but rather
are applied to the scope object.
@@ -241,8 +255,8 @@ describe('myController function', function() {
</pre>
If you need to test a nested controller one needs to create the same scope hierarchy
in your test as exist in the DOM.
If you need to test a nested controller you need to create the same scope hierarchy
in your test that exists in the DOM.
<pre>
describe('state', function() {
@@ -2,16 +2,16 @@
@name Developer Guide: About MVC in Angular: Understanding the Model Component
@description
Depending on the context of the discussion in angular documentation, the term _model_ can refer to
Depending on the context of the discussion in the Angular documentation, the term _model_ can refer to
either a single object representing one entity (for example, a model called "phones" with its value
being an array of phones) or the entire data model for the application (all entities).
In angular, a model is any data that is reachable as a property of an angular {@link
In Angular, a model is any data that is reachable as a property of an angular {@link
scope Scope} object. The name of the property is the model identifier and the value is
any JavaScript object (including arrays and primitives).
The only requirement for a JavaScript object to be a model in angular is that the object must be
referenced by an angular scope as a property of that scope object. This property reference can be
The only requirement for a JavaScript object to be a model in Angular is that the object must be
referenced by an Angular scope as a property of that scope object. This property reference can be
created explicitly or implicitly.
You can create models by explicitly creating scope properties referencing JavaScript objects in the
@@ -52,11 +52,11 @@ cloud".
The code above creates one child scope for each item in the "phones" array and creates a "phone"
object (model) on each of these scopes with its value set to the value of "phone" in the array.
In angular, a JavaScript object stops being a model when:
In Angular, a JavaScript object stops being a model when:
* No angular scope contains a property that references the object.
* No Angular scope contains a property that references the object.
* All angular scopes that contain a property referencing the object become stale and eligible for
* All Angular scopes that contain a property referencing the object become stale and eligible for
garbage collection.
The following illustration shows a simple data model created implicitly from a simple template:
@@ -2,14 +2,14 @@
@name Developer Guide: About MVC in Angular: Understanding the View Component
@description
In angular, the view is the DOM loaded and rendered in the browser, after angular has transformed
In Angular, the view is the DOM loaded and rendered in the browser, after Angular has transformed
the DOM based on information in the template, controller and model.
<img src="img/guide/about_view_final.png">
In the angular implementation of MVC, the view has knowledge of both the model and the controller.
In the Angular implementation of MVC, the view has knowledge of both the model and the controller.
The view knows about the model where two-way data-binding occurs. The view has knowledge of the
controller through angular directives, such as {@link api/ng.directive:ngController
controller through Angular directives, such as {@link api/ng.directive:ngController
ngController} and {@link api/ng.directive:ngView ngView}, and through bindings of this form:
`{{someControllerFunction()}}`. In these ways, the view can call functions in an associated
controller function.
@@ -73,10 +73,9 @@ Any time your application needs to react to a change in the current URL or if yo
the current URL in the browser.
## What does it not do?
Does not cause a full page reload when the browser URL is changed. To reload the page after
It does not cause a full page reload when the browser URL is changed. To reload the page after
changing the URL, use the lower-level API, `$window.location.href`.
# General overview of the API
The `$location` service can behave differently, depending on the configuration that was provided to
@@ -133,12 +132,12 @@ current URL without creating a new browser history record you can call:
// or you can chain these as: $location.path('/someNewPath').replace();
</pre>
Note that the setters don't update `window.location` immediately. Instead, `$location` service is
Note that the setters don't update `window.location` immediately. Instead, the `$location` service is
aware of the {@link api/ng.$rootScope.Scope scope} life-cycle and coalesces multiple `$location`
mutations into one "commit" to the `window.location` object during the scope `$digest` phase. Since
multiple changes to the $location's state will be pushed to the browser as a single change, it's
enough to call the `replace()` method just once to make the entire "commit" a replace operation
rather than addition to the browser history. Once the browser is updated, the $location service
rather than an addition to the browser history. Once the browser is updated, the $location service
resets the flag set by `replace()` method and future mutations will create new history records,
unless `replace()` is called again.
@@ -212,7 +211,7 @@ In this mode, `$location` uses Hashbang URLs in all browsers.
<pre>
it('should show example', inject(
function($locationProvider) {
$locationProvider.html5mode = false;
$locationProvider.html5Mode(false);
$locationProvider.hashPrefix = '!';
},
function($location) {
@@ -261,7 +260,7 @@ having to worry about whether the browser displaying your app supports the histo
<pre>
it('should show example', inject(
function($locationProvider) {
$locationProvider.html5mode = true;
$locationProvider.html5Mode(true);
$locationProvider.hashPrefix = '!';
},
function($location) {
@@ -304,7 +303,7 @@ history API or not; the `$location` service makes this transparent to you.
### Html link rewriting
When you use the history API mode, you will need different links in different browser, but all you
When you use HTML5 history API mode, you will need different links in different browsers, but all you
have to do is specify regular URL links, such as: `<a href="/some?foo=bar">link</a>`
When a user clicks on this link,
@@ -48,9 +48,9 @@ create this instance when called.
# Dependencies
Services can not only be depended upon, but also have its own dependencies. These can be specified
as arguments of the factory function. {@link di Read more} about the DI
in Angular and the use of array notation and $inject property to make DI annotation
Services can not only be depended upon, but can also have their own dependencies. These can be specified
as arguments of the factory function. {@link di Read more} about dependency injection (DI)
in Angular and the use of array notation and the $inject property to make DI annotation
minification-proof.
Following is an example of a very simple service. This service depends on the `$window` service
@@ -78,7 +78,7 @@ angular.module('myModule', [], function($provide) {
All services in Angular are instantiated lazily. This means that a service will be created
only when it is needed for instantiation of a service or an application component that depends on it.
In other words, Angular won't instantiate lazy services unless they are requested directly or
In other words, Angular won't instantiate services unless they are requested directly or
indirectly by the application.
@@ -39,8 +39,8 @@ function myModuleCfgFn($provide) {
</pre>
Here is an example of two services that depend on each other, as well as on other services that are
provided by Angular's web framework:
Here is an example of two services, one of which depends on the other and both
of which depend on other services that are provided by the Angular framework:
<pre>
/**
+3 -4
View File
@@ -2,10 +2,9 @@
@name Developer Guide: Angular Services
@description
Services are a feature that angular brings to client-side web apps from the server side, where
services have been commonly used for a long time. Services in angular apps are substitutable
objects that are wired together using {@link di dependency injection (DI)}. Services are
most often used with {@link di dependency injection}, also a key feature of angular apps.
Services are a feature that Angular brings to client-side web apps from the server side, where
services have been commonly used for a long time. Services in Angular apps are substitutable
objects that are wired together using {@link di dependency injection (DI)}.
## Related Topics
@@ -6,9 +6,9 @@ Angular services are singletons that carry out specific tasks common to web apps
{@link api/ng.$http $http service} that provides low level access to the browser's
`XMLHttpRequest` object.
To use an angular service, you identify it as a dependency for the dependent (a controller, or
To use an Angular service, you identify it as a dependency for the dependent (a controller, or
another service) that depends on the service. Angular's dependency injection subsystem takes care
of the rest. The angular injector subsystem is in charge of service instantiation, resolution of
of the rest. The Angular injector subsystem is in charge of service instantiation, resolution of
dependencies, and provision of dependencies to factory functions as requested.
Angular injects dependencies using "constructor" injection (the service is passed in via a factory
@@ -18,7 +18,7 @@ must explicitly define its dependencies by using the `$inject` property. For ex
myController.$inject = ['$location'];
The angular web framework provides a set of services for common operations. Like other core angular
The Angular web framework provides a set of services for common operations. Like other core Angular
variables and identifiers, the built-in services always start with `$` (such as `$http` mentioned
above). You can also create your own custom services.
@@ -2,8 +2,8 @@
@name Developer Guide: Templates: Data Binding in Angular
@description
Data-binding in angular web apps is the automatic syncing of data between the model and view
components. The way that angular implements data-binding lets you treat the model as the
Data-binding in Angular web apps is the automatic syncronization of data between the model and view
components. The way that Angular implements data-binding lets you treat the model as the
single-source-of-truth in your application. The view is a projection of the model at all times.
When the model changes, the view reflects the change, and vice versa.
@@ -19,7 +19,7 @@ to write code that constantly syncs the view with the model and the model with t
## Data Binding in Angular Templates
<img class="right" src="img/Two_Way_Data_Binding.png"/>
The way angular templates works is different, as illustrated in the diagram. They are different
The way Angular templates works is different, as illustrated in the diagram. They are different
because first the template (which is the uncompiled HTML along with any additional markup or
directives) is compiled on the browser, and second, the compilation step produces a live view. We
say live because any changes to the view are immediately reflected in the model, and any changes in
+5 -5
View File
@@ -2,13 +2,13 @@
@name Developer Guide: Understanding Angular Templates
@description
An angular template is the declarative specification that, along with information from the model
An Angular template is the declarative specification that, along with information from the model
and controller, becomes the rendered view that a user sees in the browser. It is the static DOM,
containing HTML, CSS, and angular-specific elements and angular-specific element attributes. The
angular elements and attributes direct angular to add behavior and transform the template DOM into
Angular elements and attributes direct angular to add behavior and transform the template DOM into
the dynamic view DOM.
These are the types of angular elements and element attributes you can use in a template:
These are the types of Angular elements and element attributes you can use in a template:
* {@link guide/directive Directive} — An attribute or element that
augments an existing DOM element or represents a reusable DOM component - a widget.
@@ -20,8 +20,8 @@ curly brace notation `{{ }}` to bind expressions to elements is built-in angular
Note: In addition to declaring the elements above in templates, you can also access these elements
in JavaScript code.
The following code snippet shows a simple angular template made up of standard HTML tags along with
angular {@link guide/directive directives} and curly-brace bindings
The following code snippet shows a simple Angular template made up of standard HTML tags along with
Angular {@link guide/directive directives} and curly-brace bindings
with {@link expression expressions}:
<pre>
+46 -31
View File
@@ -5,35 +5,47 @@
JavaScript is a dynamically typed language which comes with great power of expression, but it also
come with almost no-help from the compiler. For this reason we feel very strongly that any code
written in JavaScript needs to come with a strong set of tests. We have built many features into
angular which makes testing your angular applications easy. So there is no excuse for not do it.
Angular which makes testing your Angular applications easy. So there is no excuse for not testing.
# It is all about NOT mixing concerns
Unit testing as the name implies is about testing individual units of code. Unit tests try to
answer the question: Did I think about the logic correctly. 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 it.
That is because when we are testing the sort function we don't want to be forced into crating
related pieces such as the DOM elements, or making any XHR calls in getting the data to sort. While
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.
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 time mix concerns, and they end up with 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
manipulates the DOM. With angular we try to make it easy for you to do the right thing, and so we
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
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. 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, you may very well end up with an untestable application.
DOM in the right way.
## Dependency Inject
## 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.
## 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 know place, also known as global singleton.
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? Must likely by looking it up in a well know place. See #2)
4. You could expect that the it be handed to you.
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.
Out of the list above only the last of is testable. Lets look at why:
Out of the four options in the list above, only the last one is testable. Let's look at why:
### Using the `new` operator
@@ -52,10 +64,10 @@ function MyClass() {
}
</pre>
The issue becomes, that in tests, we would very much like to instantiate a `MockXHR` which would
The issue becomes that in tests, we would very much like to instantiate a `MockXHR` which would
allow us to return fake data and simulate network failures. By calling `new XHR()` we are
permanently bound to the actual one, and there is no good way to replace it. Yes there is monkey
patching, that is a bad idea for many reasons, which is outside the scope of this document.
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.
The class above is hard to test since we have to resort to monkey patching:
<pre>
@@ -69,7 +81,7 @@ XHR = oldXHR; // if you forget this bad things will happen
### Global look-up:
Another way to approach the problem is 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() {
@@ -83,7 +95,7 @@ function MyClass() {
}
</pre>
While no new instance of dependency is being created, it is fundamentally the same as `new`, in
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
through monkey patching. The basic issue for testing is that 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
@@ -119,7 +131,7 @@ function MyClass() {
}
</pre>
However, where dose the serviceRegistry come from? if it is:
However, where does the serviceRegistry come from? if it is:
* `new`-ed up, the 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).
@@ -164,7 +176,7 @@ 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 which makes the right thing
easy to do, but you still need to do it if you wish to take advantage of the testability story.
## Controllers
@@ -173,7 +185,7 @@ for your application is mixed in with DOM manipulation, it will be hard to test
below:
<pre>
function PasswordController() {
function PasswordCtrl() {
// get references to DOM elements
var msg = $('.ex1 span');
var input = $('.ex1 input');
@@ -197,7 +209,7 @@ function PasswordController() {
}
</pre>
The code above is problematic from testability, 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>
@@ -207,7 +219,7 @@ $('body').html('<div class="ex1">')
.find('div')
.append(input)
.append(span);
var pc = new PasswordController();
var pc = new PasswordCtrl();
input.val('abc');
pc.grade();
expect(span.text()).toEqual('weak');
@@ -218,7 +230,7 @@ In angular the controllers are strictly separated from the DOM manipulation logi
a much easier testability story as can be seen in this example:
<pre>
function PasswordCntrl($scope) {
function PasswordCtrl($scope) {
$scope.password = '';
$scope.grade = function() {
var size = $scope.password.length;
@@ -233,19 +245,18 @@ function PasswordCntrl($scope) {
}
</pre>
and the tests is straight forward
and the test is straight forward
<pre>
var pc = new PasswordController();
var pc = new PasswordCtrl();
pc.password('abc');
pc.grade();
expect(span.strength).toEqual('weak');
expect(pc.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
that such a test tells a story, rather then asserting random bits which don't seem to be related.
## Filters
{@link api/ng.$filter Filters} are functions which transform the data into user readable
format. They are important because they remove the formatting responsibility from the application
@@ -266,16 +277,20 @@ expect(length('abc')).toEqual(3);
## Directives
Directives in angular are responsible for updating the DOM when the state of the model changes.
## Mocks
oue
## Global State Isolation
oue
# Preferred way of Testing
uo
## JavaScriptTestDriver
ou
## Jasmine
ou
## Sample project
uoe
+14 -16
View File
@@ -47,7 +47,7 @@ is simply handed the `greeter` at runtime.
This is desirable, but it puts the responsibility of getting hold of the dependency onto the
code responsible for the construction of `SomeClass`.
To manage the responsibility of dependency creation, each angular application has an {@link
To manage the responsibility of dependency creation, each Angular application has an {@link
api/angular.injector injector}. The injector is a service locator that is responsible for
construction and lookup of dependencies.
@@ -67,11 +67,11 @@ Here is an example of using the injector service.
$window.alert(text);
}
};
}).
});
// New injector is created from the module.
// (This is usually done automatically by angular bootstrap)
var injector = angular.injector('myModule');
var injector = angular.injector(['myModule', 'ng']);
// Request any dependency from the injector
var greeter = injector.get('greeter');
@@ -92,7 +92,7 @@ dependency lookup responsibility to the injector by declaring the dependencies a
// And this controller definition
function MyController($scope, greeter) {
$scope.sayHello = function() {
greeter('Hello World');
greeter.greet('Hello World');
};
}
@@ -109,7 +109,7 @@ deal with the injector. This setup does not break the Law of Demeter.
How does the injector know what service needs to be injected?
The application developer needs to provide annotation information, that the injector uses in order
The application developer needs to provide annotation information that the injector uses in order
to resolve the dependencies. Throughout Angular certain API functions are invoked using the
injector, as per the API documentation. The injector needs to know what services to inject into
the function. Below are three equivalent ways of annotating your code with service name
@@ -186,32 +186,30 @@ For this reason the third annotation style is provided as well.
Keep in mind that all of the annotation styles are equivalent and can be used anywhere in Angular
where injection is supported.
# Where can I use DI?
DI is pervasive throughout Angular. It is typically used in controllers and factory methods.
## DI in controllers
Controllers are classes which are responsible for application behavior. Recommended way of
Controllers are classes which are responsible for application behavior. The recommended way of
declaring controllers is:
<pre>
var MyController = function(dep1, dep2) {
...
}
MyController.$inject = ['dep1', 'dep2'];
MyController.prototype.aMethod = function() {
var MyController = function($scope, dep1, dep2) {
...
$scope.aMethod = function() {
...
}
}
MyController.$inject = ['$scope', 'dep1', 'dep2'];
</pre>
## Factory methods
Factory methods are responsible for creating most objects in Angular. Examples are directives,
services, and filters. The factory methods are register with the module, and the recommended way
services, and filters. The factory methods are registered with the module, and the recommended way
of declaring factories is:
<pre>
@@ -231,4 +229,4 @@ of declaring factories is:
run(['depService', function(depService) {
...
}]);
</pre>
</pre>
+26 -24
View File
@@ -110,7 +110,7 @@ Compilation of HTML happens in three phases:
## Reasons behind the compile/link separation
At this point you may wonder why the compile process is broken down to a compile and link phase.
To understand this, let's look at a real world example with repeater:
To understand this, let's look at a real world example with a repeater:
<pre>
Hello {{user}}, you have these actions:
@@ -144,9 +144,9 @@ links a specific instance of the {@link api/ng.$rootScope.Scope scope} and the s
instance of an `li` is performed.
{@link api/ng.directive:ngRepeat ngRepeat} works by preventing the
compilation process form descending into the `li` element. Instead the {@link
compilation process from descending into the `li` element. Instead the {@link
api/ng.directive:ngRepeat ngRepeat} directive compiles `li`
separately. The result of of the `li` element compilation is a linking function which contains all
separately. The result of the `li` element compilation is a linking function which contains all
of the directives contained in the `li` element, ready to be attached to a specific clone of the `li`
element. At runtime the {@link api/ng.directive:ngRepeat ngRepeat}
watches the expression and as items are added to the array it clones the `li` element, creates a
@@ -296,7 +296,7 @@ makes it injectable following all of the rules of injection annotation.
The directive definition object provides instructions to the {@link api/ng.$compile
compiler}. The attributes are:
* `name` - Name of the current scope. Optional defaults to the name at registration.
* `name` - Name of the current scope. Optional and defaults to the name at registration.
* `priority` - When there are multiple directives defined on a single DOM element, sometimes it
is necessary to specify the order in which the directives are applied. The `priority` is used
@@ -310,7 +310,7 @@ compiler}. The attributes are:
* `scope` - If set to:
* `true` - then a new scope will be created for this directive. If multiple directives on the
same element request new scope, only one new scope is created. The new scope rule does not
same element request a new scope, only one new scope is created. The new scope rule does not
apply for the root of the template since the root of the template always gets a new scope.
* `{}` (object hash) - then a new 'isolate' scope is created. The 'isolate' scope differs from
@@ -342,11 +342,11 @@ compiler}. The attributes are:
If no `attr` name is specified then the attribute name is assumed to be the same as the
local name. Given `<widget my-attr="count = count + value">` and widget definition of
`scope: { localFn:'&myAttr' }`, then isolate scope property `localFn` will point to
a function wrapper for the `increment()` expression. Often it's desirable to pass data from
the isolate scope via an expression and to the parent scope, this can be done by passing a
map of local variable names and values into the expression wrapper fn. For example, if the
expression is `increment(amount)` then we can specify the amount value by calling the
`localFn` as `localFn({amount: 22})`.
a function wrapper for the `count = count + value` expression. Often it's desirable to
pass data from the isolated scope via an expression and to the parent scope, this can be
done by passing a map of local variable names and values into the expression wrapper fn.
For example, if the expression is `increment(amount)` then we can specify the amount value
by calling the `localFn` as `localFn({amount: 22})`.
* `controller` - Controller constructor function. The controller is instantiated before the
pre-linking phase and it is shared with other directives if they request it by name (see
@@ -474,7 +474,7 @@ compiler linking function will fail to locate the correct elements for linking.
### Post-linking function
Executed after the child elements are linked. Safe to do DOM transformation in here.
Executed after the child elements are linked. It is safe to do DOM transformation in the post-linking function.
<a name="Attributes"></a>
## Attributes
@@ -528,6 +528,7 @@ dialog component may work.
on-ok="show = false; doSomething()">
Body goes here: {{username}} is {{title}}.
</dialog>
</div>
</pre>
Clicking on the "show" button will open the dialog. The dialog will have a title, which is
@@ -537,7 +538,7 @@ into the dialog.
Here is an example of what the template definition for the `dialog` widget may look like.
<pre>
<div ng-show="show">
<div ng-show="visible">
<h3>{{title}}</h3>
<div class="body" ng-transclude></div>
<div class="footer">
@@ -549,18 +550,18 @@ Here is an example of what the template definition for the `dialog` widget may l
This will not render properly, unless we do some scope magic.
The first issue we have to solve is that the dialog box template expect `title` to be defined, but
the place of instantiation would like to bind to `username`. Furthermore the buttons expect `onOk`
as well as `onCancel` functions to be present in the scope. This limits the usefulness of the
The first issue we have to solve is that the dialog box template expects `title` to be defined, but
the place of instantiation would like to bind to `username`. Furthermore the buttons expect the
`onOk` and `onCancel` functions to be present in the scope. This limits the usefulness of the
widget. To solve the mapping issue we use the `locals` to create local variables which the template
expects as follows:
<pre>
scope: {
title: '=', // set up title to accept data-binding
title: '@', // the title uses the data-binding from the parent scope
onOk: '&', // create a delegate onOk function
onCancel: '&', // create a delegate onCancel function
show: '='
visible: '=' // set up visible to accept data-binding
}
</pre>
@@ -583,7 +584,7 @@ isolated scope then it will not be able to bind to anything. For this reason the
is a child of the original scope, before the widget created an isolated scope for its local
variables. This makes the transcluded and widget isolated scope siblings.
This may seem as unexpected complexity, but it gives the widget user and developer the least
This may seem to be unexpected complexity, but it gives the widget user and developer the least
surprise.
Therefore the final directive definition looks something like this:
@@ -591,11 +592,13 @@ Therefore the final directive definition looks something like this:
<pre>
transclude: true,
scope: {
title: 'bind', // set up title to accept data-binding
onOk: 'expression', // create a delegate onOk function
onCancel: 'expression', // create a delegate onCancel function
show: 'accessor' // create a getter/setter function for visibility.
}
title: '@', // the title uses the data-binding from the parent scope
onOk: '&', // create a delegate onOk function
onCancel: '&', // create a delegate onCancel function
visible: '=' // set up visible to accept data-binding
},
restrict: 'E',
replace: true
</pre>
# Creating Components
@@ -606,7 +609,6 @@ can be built.
Following is an example of building a reusable widget.
<doc:example module="zippyModule">
<doc:source>
<script>
+9 -10
View File
@@ -15,10 +15,9 @@ For example, these are all valid expressions in angular:
## Angular Expressions vs. JS Expressions
It might be tempting to think of angular view expressions as JavaScript expressions, but that is
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
differences:
It might be tempting to think of Angular view expressions as JavaScript expressions, but that is
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
evaluation, unlike in JavaScript where the expressions are evaluated against the global
@@ -92,9 +91,9 @@ You can try evaluating different expressions here:
# Property Evaluation
Evaluation of all properties takes place against a scope. Unlike JavaScript, where names default
to global window properties, angular expressions have to use {@link api/ng.$window
to global window properties, Angular expressions have to use {@link api/ng.$window
`$window`} to refer to the global `window` object. For example, if you want to call `alert()`, which is
defined on `window`, in an expression must use `$window.alert()`. This is done intentionally to
defined on `window`, in an expression you must use `$window.alert()`. This is done intentionally to
prevent accidental access to the global state (a common source of subtle bugs).
<doc:example>
@@ -148,7 +147,7 @@ Similarly, invoking a function `a.b.c()` on undefined or null simply returns und
## No Control Flow Statements
You cannot write a control flow statement in an expression. The reason behind this is core to the
angular philosophy that application logic should be in controllers, not in the view. If you need a
Angular philosophy that application logic should be in controllers, not in the view. If you need a
conditional, loop, or to throw from a view expression, delegate to a JavaScript method instead.
@@ -179,9 +178,9 @@ You might be wondering, what is the significance of the $ prefix? It is simply a
angular uses, to differentiate its API names from others. If angular didn't use $, then evaluating
`a.length()` would return undefined because neither a nor angular define such a property.
Consider that in a future version of angular we might choose to add a length method, in which case
Consider that in a future version of Angular we might choose to add a length method, in which case
the behavior of the expression would change. Worse yet, you the developer could create a length
property and then we would have a collision. This problem exists because angular augments existing
property and then we would have a collision. This problem exists because Angular augments existing
objects with additional behavior. By prefixing its additions with $ we are reserving our namespace
so that angular developers and developers who use angular can develop in harmony without collisions.
so that angular developers and developers who use Angular can develop in harmony without collisions.
+9 -9
View File
@@ -12,9 +12,9 @@ Server-side validation is still necessary for a secure application.
# Simple form
The key directive in understanding two-way data-binding is {@link api/ng.directive:ngModel ngModel}.
The key directive in understanding two-way data-binding is {@link api/ng.directive:ngModel ngModel}.
The `ngModel` directive provides the two-way data-binding by synchronizing the model to the view, as well as view to the model.
In addition it provides {@link api/ng.directive:ngModel.NgModelController API} for other directives to augment its behavior.
In addition it provides an {@link api/ng.directive:ngModel.NgModelController API} for other directives to augment its behavior.
<doc:example>
<doc:source>
@@ -63,7 +63,7 @@ To allow styling of form as well as controls, `ngModel` add these CSS classes:
- `ng-pristine`
- `ng-dirty`
Following example uses the CSS to display validity of each form control.
The following example uses the CSS to display validity of each form control.
In the example both `user.name` and `user.email` are required, but are rendered with red background only when they are dirty.
This ensures that the user is not distracted with an error until after interacting with the control, and failing to satisfy its validity.
@@ -190,18 +190,18 @@ The validation can occur in two places:
* **View to Model update** -
In a similar way, whenever a user interacts with a control it calls {@link api/ng.directive:ngModel.NgModelController#$setViewValue NgModelController#$setViewValue}.
This in turn pipelines all functions in {@link api/ng.directive:ngModel.NgModelController#$parsers NgModelController#$parsers} array, so that each of these functions has an opportunity to convert the value and change validity state of the form control through {@link api/ng.directive:ngModel.NgModelController#$setValidity NgModelController#$setValidity}.
This in turn pipelines all functions in the {@link api/ng.directive:ngModel.NgModelController#$parsers NgModelController#$parsers} array, so that each of these functions has an opportunity to convert the value and change validity state of the form control through {@link api/ng.directive:ngModel.NgModelController#$setValidity NgModelController#$setValidity}.
In the following example we create two directives.
* The first one is `integer` and it validates whether the input is a valid integer.
For example `1.23` is an invalid value, since it contains a fraction.
Note, that we unshift the array instead of pushing.
Note that we unshift the array instead of pushing.
This is because we want to be first parser and consume the control string value, as we need to execute the validation function before a conversion to number occurs.
* The second directive is a `smart-float`.
It parses both `1.2` and `1,2` into a valid float number `1.2`.
Note that, we can't use input type `number` here as HTML5 browsers would not allow the user to type what it would consider an invalid number such as `1,2`.
Note that we can't use input type `number` here as HTML5 browsers would not allow the user to type what it would consider an invalid number such as `1,2`.
<doc:example module="form-example1">
@@ -272,7 +272,7 @@ In the following example we create two directives.
</doc:example>
# Implementing custom form control (using `ngModel`)
# Implementing custom form controls (using `ngModel`)
Angular implements all of the basic HTML form controls ({@link api/ng.directive:input input}, {@link api/ng.directive:select select}, {@link api/ng.directive:textarea textarea}), which should be sufficient for most cases.
However, if you need more flexibility, you can write your own form control as a directive.
@@ -300,8 +300,8 @@ The following example shows how to add two-way data-binding to contentEditable e
});
// model -> view
ctrl.$render = function(value) {
elm.html(value);
ctrl.$render = function() {
elm.html(ctrl.$viewValue);
};
// load init value from DOM
+2 -2
View File
@@ -5,12 +5,12 @@
# Overview
This document describes the Internet Explorer (IE) idiosyncrasies when dealing with custom HTML
attributes and tags. Read this document if you are planning on deploying your angular application
attributes and tags. Read this document if you are planning on deploying your Angular application
on IE v8.0 or earlier.
# Short Version
To make your angular application work on IE please make sure that:
To make your Angular application work on IE please make sure that:
1. You polyfill JSON.stringify if necessary (IE7 will need this). You can use
[JSON2](https://github.com/douglascrockford/JSON-js) or
+8 -8
View File
@@ -6,7 +6,7 @@ Angular is pure client-side technology, written entirely in JavaScript. It works
long-established technologies of the web (HTML, CSS, and JavaScript) to make the development of
web apps easier and faster than ever before.
One important way that angular simplifies web development is by increasing the level of abstraction
One important way that Angular simplifies web development is by increasing the level of abstraction
between the developer and most low-level web app development tasks. Angular automatically takes
care of many of these tasks, including:
@@ -14,10 +14,10 @@ care of many of these tasks, including:
* Setting Up Listeners and Notifiers
* Input Validation
Because angular handles much of the work involved in these tasks, developers can concentrate more
Because Angular handles much of the work involved in these tasks, developers can concentrate more
on application logic and less on repetitive, error-prone, lower-level coding.
At the same time that angular simplifies the development of web apps, it brings relatively
At the same time that Angular simplifies the development of web apps, it brings relatively
sophisticated techniques to the client-side, including:
* Separation of data, application logic, and presentation components
@@ -31,12 +31,12 @@ These techniques have been for the most part absent from the client-side for far
## Single-page / Round-trip Applications
You can use angular to develop both single-page and round-trip apps, but angular is designed
You can use Angular to develop both single-page and round-trip apps, but Angular is designed
primarily for developing single-page apps. Angular supports browser history, forward and back
buttons, and bookmarking in single-page apps.
You normally wouldn't want to load angular with every page change, as would be the case with using
angular in a round-trip app. However, it would make sense to do so if you were adding a subset of
angular's features (for example, templates to leverage angular's data-binding feature) to an
You normally wouldn't want to load Angular with every page change, as would be the case with using
Angular in a round-trip app. However, it would make sense to do so if you were adding a subset of
Angular's features (for example, templates to leverage angular's data-binding feature) to an
existing round-trip app. You might follow this course of action if you were migrating an older app
to a single-page angular app.
to a single-page Angular app.
+3 -3
View File
@@ -194,7 +194,7 @@ and thus script loaders can take advantage of this property and parallelize the
# Unit Testing
In its simplest form a unit-test is a way of instantiating a subset of the application in test and
In its simplest form a unit test is a way of instantiating a subset of the application in test and
then applying a stimulus to it. It is important to realize that each module can only be loaded
once per injector. Typically an app has only one injector. But in tests, each test has its own
injector, which means that the modules are loaded multiple times per VM. Properly structured
@@ -222,8 +222,8 @@ In all of these examples we are going to assume this module definition:
Let's write some tests:
<pre>
describe('myApp', function() {
// load the application relevant modules then load a special
// test module which overrides the $window with mock version,
// load the relevant application modules then load a special
// test module which overrides the $window with a mock version,
// so that calling window.alert() will not block the test
// runner with a real alert box. This is an example of overriding
// configuration information in tests.
+5 -5
View File
@@ -16,7 +16,7 @@ declarative language for static documents. It does not contain much in the way o
applications, and as a result building web applications is an exercise in *what do I have to do, so
that I trick the browser in to doing what I want.*
Impedance mismatch between dynamic applications and static documents are often solved as:
The impedance mismatch between dynamic applications and static documents is often solved as:
* **library** - a collection of functions which are useful when writing web apps. Your code is
in charge and it calls into the library when it sees fit. E.g., `jQuery`.
@@ -111,7 +111,7 @@ concepts which the application developer may face:
Try out the Live Preview above, and then let's walk through the example and describe what's going
on.
In the `<html>` tag, we specify that it is an angular
In the `<html>` tag, we specify that it is an Angular
application with the `ng-app` directive. The `ng-app` will cause Angular to {@link
bootstrap auto initialize} your application.
@@ -121,7 +121,7 @@ We load Angular using the `<script>` tag:
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/?.?.?/angular.min.js"></script>
From the `ng-model` attribute of the `<input>` tags, angular automatically sets up two-way data
From the `ng-model` attribute of the `<input>` tags, Angular automatically sets up two-way data
binding, and we also demonstrate some easy input validation:
Quantity: <input type="integer" min="0" ng-model="qty" required >
@@ -129,7 +129,7 @@ binding, and we also demonstrate some easy input validation:
These input widgets look normal enough, but consider these points:
* When this page loaded, angular bound the names of the input widgets (`qty` and `cost`) to
* When this page loaded, Angular bound the names of the input widgets (`qty` and `cost`) to
variables of the same name. Think of those variables as the "Model" component of the
Model-View-Controller design pattern.
* Note that the HTML widget {@link api/ng.directive:input input}
@@ -193,7 +193,7 @@ Angular frees you from the following pain:
code. Angular eliminates almost all of this boilerplate, leaving code that describes the
overall flow of the application rather than all of the implementation details.
* **Writing tons of initialization code just to get started:** Typically you need to write a lot
of plumbing just to get a basic "Hello World" AJAX app working. With angular you can bootstrap
of plumbing just to get a basic "Hello World" AJAX app working. With Angular you can bootstrap
your app easily using services, which are auto-injected into your application in a {@link
http://code.google.com/p/google-guice/ Guice}-like dependency-injection style. This allows you
to get started developing features quickly. As a bonus, you get full control over the
+4 -4
View File
@@ -81,7 +81,7 @@ Logically the rendering of `{{greeting}}` involves:
You can think of the scope and its properties as the data which is used to render the view. The
scope is the single source-of-truth for all things view related.
From testability, the separation of the controller and the view is desirable, because it allows us
From a testability point of view, the separation of the controller and the view is desirable, because it allows us
to test the behavior without being distracted by the rendering details.
<pre>
@@ -151,7 +151,7 @@ This example illustrates scopes in application, and prototypical inheritance of
</file>
</example>
Notice that the Angular automatically places `ng-scope` class on elements where scopes are
Notice that Angular automatically places `ng-scope` class on elements where scopes are
attached. The `<style>` definition in this example highlights in red the new scope locations. The
child scopes are necessary because the repeater evaluates `{{employee.name}}` expression, but
depending on which scope the expression is evaluated it produces different result. Similarly the
@@ -166,7 +166,7 @@ purposes. (It is unlikely that one would need to retrieve scopes in this way ins
application.) The location where the root scope is attached to the DOM is defined by the location
of {@link api/ng.directive:ngApp `ng-app`} directive. Typically
`ng-app` is placed an the `<html>` element, but it can be placed on other elements as well, if,
for example, only a portion of the view needs to be controlled by angular.
for example, only a portion of the view needs to be controlled by Angular.
To examine the scope in the debugger:
@@ -218,7 +218,7 @@ api/ng.$rootScope.Scope#$emit emitted} to scope parents.
## Scope Life Cycle
The normal flow of browser receiving an event is that it executes a corresponding JavaScript
The normal flow of a browser receiving an event is that it executes a corresponding JavaScript
callback. Once the callback completes the browser re-renders the DOM and returns to waiting for
more events.
+5 -1
View File
@@ -123,7 +123,11 @@ minified AngularJS files:
git remote add upstream https://github.com/angular/angular.js.git
4. To build AngularJS, run:
4. To add node.js dependencies
npm install
5. To build AngularJS, run:
rake package
+10 -7
View File
@@ -2,10 +2,9 @@
@name Downloading
@description
# Including angular scripts from the angular server
The quickest way to get started is to point your html `<script>` tag to a
<http://code.angularjs.org/> URL. This way, you don't have to download anything or maintain a
local copy.
# Including angular scripts from the Google CDN
The quickest way to get started is to point your html `<script>` tag to a Google CDN URL.
This way, you don't have to download anything or maintain a local copy.
There are two types of angular script URLs you can point to, one for development and one for
production:
@@ -15,21 +14,25 @@ development.
* __angular-<version>.min.js__ — This is the minified version, which we strongly suggest you use in
production.
To point your code to an angular script on the angular server, use the following template. This
example points to (non-minified) version 1.0.2:
To point your code to an angular script on the Google CDN server, use the following template. This
example points to the minified version 1.0.2:
<pre>
<!doctype html>
<html ng-app>
<head>
<title>My Angular App</title>
<script src="http://code.angularjs.org/1.0.2/angular.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.2/angular.min.js"></script>
</head>
<body>
</body>
</html>
</pre>
Note that only versions 1.0.1 and above are available on the CDN, if you need an earlier version
you can use the <http://code.angularjs.org/> URL which was the previous recommended location for
hosted code source. If you're still using the angular server you should switch to the CDN version
for even faster loading times.
# Downloading and hosting angular files locally
This option is for those who want to work with angular offline, or those who want to host the
+27 -4
View File
@@ -32,7 +32,7 @@ templating systems.
### Do I need to worry about security holes in AngularJS?
Like with any technology, AngularJS is not impervious to attack. Angular does, however, provide
Like any other technology, AngularJS is not impervious to attack. Angular does, however, provide
built-in protection from basic security holes including cross-site scripting and HTML injection
attacks. AngularJS does round-trip escaping on all strings for you and even offers XSRF protection
for server-side communication.
@@ -90,15 +90,38 @@ framework, provides mocks for many heavy dependencies (server-side communication
### How can I learn more about Angular?
Watch the July 28, 2010 talk
"{@link http://www.youtube.com/watch?v=elvcgVSynRg| Angular: A Radically Different Way of Building
AJAX Apps}".
Watch the July 17, 2012 talk
"{@link http://www.youtube.com/watch?v=1CpiB3Wk25U AngularJS Intro + Dependency Injection}".
### How is Angular licensed?
The MIT License.
### Can I download and use the Angular logo artwork?
Yes! You can find design files in our github repository, under "{@link https://github.com/angular/angular.js/tree/master/images/logo
angular.js/images/logo}"
The logo design is licensed under a "{@link http://creativecommons.org/licenses/by-sa/3.0/
Creative Commons Attribution-ShareAlike 3.0 Unported License}". If you have some other use in mind, contact us.
### How can I get some AngularJS schwag?
We often bring a few t-shirts and stickers to events where we're presenting. If you want to order your own, the folks who
make our schwag will be happy to do a custom run for you, based on our existing template. By using the design they have on file,
they'll waive the setup costs, and you can order any quantity you need.
**Stickers**
Contact Tom Witting (or anyone in sales) via email at tom@stickergiant.com, and tell him you want to order some AngularJS
stickers just like the ones in job #42711. You'll have to give them your own info for billing and shipping.
As long as the design stays exactly the same, {@link http://www.stickergiant.com StickerGiant} will give you a reorder discount.
**T-shirts**
Contact sales at {@link http://www.customink.com www.customink.com} and tell them you want some shirts with design name "angularjs",
just like past order #2106371. You'll have to give them your own info for billing and shipping.
As long as the design stays exactly the same, CustomInk won't charge for any set up fees, and they'll give you a reorder discount.
## Common Pitfalls
+2 -2
View File
@@ -5,8 +5,8 @@
<ul doc-tutorial-nav="1"></ul>
In order to illustrate how angular enhances standard HTML, you will create a purely *static* HTML
page and then examine how we can turn this HTML code into a template that angular will use to
In order to illustrate how Angular enhances standard HTML, you will create a purely *static* HTML
page and then examine how we can turn this HTML code into a template that Angular will use to
dynamically display the same result with any set of data.
In this step you will add some basic information about two cell phones to an HTML page.
+1 -1
View File
@@ -46,7 +46,7 @@ history (back and forward navigation) and bookmarks.
### A Note About DI, Injector and Providers
As you {@link tutorial/step_05 noticed}, {@link guide/di dependency injection} is the core feature of
As you {@link tutorial/step_05 noticed}, {@link guide/di dependency injection} (DI) is the core feature of
AngularJS, so it's important for you to understand a thing or two about how it works.
When the application bootstraps, Angular creates an injector that will be used for all DI stuff in
+1 -1
View File
@@ -3,7 +3,7 @@
@description
Our application is now complete. Feel free to experiment with the code further, and jump back to
previous steps using the `git checkout` commandx.
previous steps using the `git checkout` command.
For more details and examples of the Angular concepts we touched on in this tutorial, see the
{@link guide/ Developer Guide}.
+1 -1
View File
@@ -36,7 +36,7 @@ writer.makeDir('build/docs/', true).then(function() {
});
}).then(function printStats() {
console.log('DONE. Generated ' + docs.length + ' pages in ' + (now()-start) + 'ms.' );
}).end();
}).done();
function writeTheRest(writesFuture) {
+2 -2
View File
@@ -122,7 +122,7 @@
<li><a href="http://angularjs.org"><i class="icon-home icon-white"></i> Home</a></li>
<li class="divider-vertical"></li>
<li class="dropdown">
<a href="" class="dropdown-toggle" data-toggle="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
<i class="icon-eye-open icon-white"></i> Learn <b class="caret"></b>
</a>
<ul class="dropdown-menu">
@@ -148,7 +148,7 @@
</li>
<li class="divider-vertical"></li>
<li class="dropdown">
<a href="" class="dropdown-toggle" data-toggle="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
<i class="icon-comment icon-white"></i> Discuss <b class="caret"></b>
</a>
<ul class="dropdown-menu">
+5 -2
View File
@@ -37,7 +37,8 @@ docsApp.directive.sourceEdit = function(getEmbeddedTemplate) {
'<ul class="dropdown-menu">' +
' <li><a ng-click="plunkr($event)" href="">In Plunkr</a></li>' +
' <li><a ng-click="fiddle($event)" href="">In JsFiddle</a></li>' +
'</ul>',
'</ul>' +
'</div>',
scope: true,
controller: function($scope, $attrs, openJsFiddle, openPlunkr) {
var sources = {
@@ -189,7 +190,9 @@ docsApp.serviceFactory.openPlunkr = function(templateMerge, formPostData, angula
});
postData['files[index.html]'] = templateMerge(indexHtmlContent, indexProp);
postData['tags[]'] = "angularjs";
postData.private = true;
postData.description = 'AngularJS Example Plunkr';
formPostData('http://plnkr.co/edit/?p=preview', postData);
+3704 -3668
View File
File diff suppressed because it is too large Load Diff
+2 -4
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -1 +1 @@
1.7.2
1.8.2
-37
View File
@@ -1,37 +0,0 @@
<!doctype html>
<!--
This test demonstrates the time difference between document's DOMContentLoaded and window's load events.
-->
<html>
<head ng:app>
<script>
startTS = new Date().getTime();
onDOMContentLoadedTS = 0; // default for browsers where DOMCL is not supported
</script>
<title>DOMContentLoaded test</title>
<script src="../build/angular.min.js"></script>
<script>
angular.element(document).bind('DOMContentLoaded', function(e) {onDOMContentLoadedTS = new Date().getTime()});
angular.element(window).bind('load', function(e) {
onloadTS = new Date().getTime();
log.innerHTML = 'start: ' + new Date(startTS) + '<br/>DOMContentLoaded: +' + (onDOMContentLoadedTS - startTS) + 'ms<br/> load: +' + (onloadTS - startTS) + 'ms';
});
</script>
</head>
<body>
<h1>DOMContentLoaded test</h1>
<p>{{ 'yay!' || 'angular starting...' }}</p>
<img width="100px" src="http://lh5.ggpht.com/_BLyMhylclm0/TST_bbGH0zI/AAAAAAAAATY/oNUn9kivKN8/s912/1020047.jpg" />
<img width="100px" src="http://lh5.ggpht.com/_MqEybfAuUFk/TSOOiegUlPI/AAAAAAAADHY/AEwEWc64_-M/s800/IMG_7294.JPG" />
<img width="100px" src="http://lh3.ggpht.com/_LdjD3ua8rpE/TSOW99rwjZI/AAAAAAAAFC0/0qJRhhN45RM/s912/Saison%2010%20%2834%29.JPG" />
<img width="100px" src="http://lh6.ggpht.com/_oy_-am3CVUw/TSOQBddZpwI/AAAAAAAACaw/ogFgoD79bVE/s912/P1100886.JPG" />
<img width="100px" src="http://lh4.ggpht.com/_srSaA7ZN7oc/TDdxXbA_i1I/AAAAAAAAQ2w/ii3vgrnfCrM/s800/Urlaub10%20157.jpg" />
<img width="100px" src="http://lh5.ggpht.com/_y6vXu6iRrfM/SIaYhRQBYNI/AAAAAAAAAmE/lV2NYwxtsQM/s912/North%20Dakota%20Trip%20014.JPG" />
<img width="100px" src="http://lh5.ggpht.com/_Jjv9cIn9cS8/RuwZCgfOl6I/AAAAAAAAAOc/QrrMe8vpawg/s800/Shark%20Trip%20-%20day%202%20513.JPG" />
<p id="log"></p>
</body>
</html>
-21
View File
@@ -1,21 +0,0 @@
describe('perf misc', function() {
it('operation speeds', function() {
perf(
function typeByTypeof() { return typeof noop == 'function'; }, // WINNER
function typeByProperty() { return noop.apply && noop.call; },
function typeByConstructor() { return noop.constructor == Function; }
);
});
it('property access', function() {
var name = 'value';
var none = 'x';
var scope = {};
perf(
function direct() { return scope.value; }, // WINNER
function byName() { return scope[name]; },
function undefinedDirect() { return scope.x; },
function undefiendByName() { return scope[none]; }
);
});
});
File diff suppressed because one or more lines are too long
-49
View File
@@ -1,49 +0,0 @@
def generate_object(f, objName, iterations)
f.write("var #{objName}='[");
iterations.times do |i|
f.write('{')
f.write('"simpleStringProperty":') #23
f.write('"some string value ' + ('%07d' % i) + '"') #27
f.write(',')
f.write('"stringWithQuotes":') #19
f.write('"some string with \\\\"quotes\\\\" ' + ('%07d' % i) + '"') #36
f.write(',')
f.write('"stringWithUnicode":')
f.write('"short string with \\u1234 unicode \\u2345 chars ' + ('%07d' % i) + '"')
f.write(',')
f.write('"aNumber":') #10
f.write(i) #?
f.write(',')
f.write('"smallArray":')
f.write('["a",23,"b",42,' + i.to_s + ']')
f.write(',')
f.write('"smallObj":')
f.write('{"foo":"bar","baz":543,"num":' + i.to_s + ',"fuz":"fuz buz huz duz ' + i.to_s + '"}')
f.write(',')
f.write('"timeStamp":')
f.write('"2010-12-22T04:58:01.' + ("%03d" % (i%1000)) + '"')
f.write('},')
end
f.write('"just a padding string"]\';' + "\n\n");
end
file_path = File.join(File.dirname(__FILE__), 'jsonParserPayload.js')
File.open(file_path, 'w') do |f|
generate_object(f, 'superTinyJsonString', 1) #~300b
generate_object(f, 'tinyJsonString', 3) #~1kb
generate_object(f, 'smallJsonString', 30) #~10kb
generate_object(f, 'mediumJsonString', 600) #~200kb
generate_object(f, 'largeJsonString', 2000) #~650kb
end
-16
View File
@@ -1,16 +0,0 @@
describe('json', function() {
it('angular parser', function() {
perf(
function angular() {
fromJson(largeJsonString);
},
function nativeDelegate() {
fromJson(largeJsonString, true);
},
function nativeJSON() {
JSON.parse(largeJsonString);
}
);
});
});
-19
View File
@@ -1,19 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html xmlns:ng="http://angularjs.org">
<head>
<script>
function el(id) {
return document.getElementById(id);
}
function update() {
el("output").innerHTML = el("input").value;
}
</script>
</head>
<body>
Your name: <input id="input" type="text" value="World"
onkeydown="setTimeout(update,0)"/>
<hr/>
Hello <span id="output">{{yourname}}</span>!
</body>
</html>
-67
View File
@@ -1,67 +0,0 @@
if (window.jstestdriver) {
jstd = jstestdriver;
dump = bind(jstd.console, jstd.console.log);
}
function time(fn) {
var count = 1,
targetTime = 500,
start = new Date().getTime(),
stop = start + targetTime,
elapsed,
end,
iterations,
pad = angularFilter.number;
// do one iteration to guess how long it will take
fn();
while((end=new Date().getTime()) < stop ){
// how much time has elapsed since we started the test
elapsed = (end-start) || 1;
// guess how many more iterations we need before we reach
// the time limit. We do this so that we spend most of our
// time in tight loop
iterations = Math.ceil(
// how much more time we need
(targetTime - elapsed)
/
2 // to prevent overrun guess low
/
// this is how much the cost is so far per iteration
(elapsed / count)
);
count += iterations;
while(iterations--) {
fn();
}
}
elapsed = end - start;
return {
count: count,
total: elapsed,
time: elapsed / count,
name: fn.name,
msg: '' + pad(elapsed / count, 3)
+ ' ms [ ' + pad(1 / elapsed * count * 1000, 0) + ' ops/sec ] '
+ '(' + elapsed + ' ms/' + count + ')'
};
}
function perf() {
var log = [],
summary = [],
i,
baseline,
pad = angularFilter.number;
for (i = 0; i < arguments.length; i++) {
var fn = arguments[i];
var info = time(fn);
if (baseline === undefined) baseline = info.time;
summary.push(info.name + ': ' + pad(baseline / info.time, 2) + ' X');
log.push('\n ' + info.name + ': ' + info.msg);
}
log.unshift(summary.join(' - '));
dump(log.join(' '));
}
-30
View File
@@ -1,30 +0,0 @@
<!DOCTYPE HTML>
<html xmlns:ng="http://angularjs.org">
<head>
<script type="text/javascript" src="../src/angular-bootstrap.js" ng:autobind></script>
</head>
<body ng:init="$window.$root = this; data = [{foo: 'foo'},{bar: 'bar'}]">
<p>This is a demo of a potential bug in angular.</p>
<p>Try the following:</p>
<ol>
<li> Type "foo" on the filter box.
<li> Clear the contents of the filter box.
<li> Type "bar" on the filter box.
<li> Clear the contents of the filter box.
</ol>
<p>Why doesn't the data goes back to the original?</p>
<hr>
Input: <input type="text" ng:model="filterName" id="filterInputField"/>
<br/>
<table ng:eval="filtered_data = data.$filter(filterName)" style="border: 1px solid black">
<tr>
<th>Foo</th>
<th>Bar</th>
</tr>
<tr ng:repeat="record in filtered_data">
<td>{{record.foo}}</td>
<td>{{record.bar}}</td>
</tr>
</table>
</body>
</html>
-10
View File
@@ -1,10 +0,0 @@
<!DOCTYPE HTML>
<html xmlns:ng="http://angularjs.org">
<script type="text/javascript" src="../src/angular-bootstrap.js" ng:autobind></script>
<body>
<span ng:init='x = {d:3}; x1 = {bar:[x,5]}; x1.bar[0].d = 4'>
<input ng:model="x1.bar[0].d" type="text"></input>
<input ng:model="x.d" type="text"></input>
<span> {{x1}} -- {{x1.bar[0].d}}</span>
</body>
</html>
-13
View File
@@ -1,13 +0,0 @@
<!DOCTYPE HTML>
<html xmlns:ng="http://angularjs.org">
<script type="text/javascript" src="../build/angular.js" ng:autobind></script>
<body ng:init="scope = { itemId: 12345 }">
<input ng:model="value" /><br />
<a id="link-1" href ng:click="value = 1">link 1</a> (link, don't reload)<br />
<a id="link-2" href="" ng:click="value = 2">link 2</a> (link, don't reload)<br />
<a id="link-3" ng:href="#{{'123'}}" ng:click="value = 3">link 3</a> (link, reload!)<br />
<a id="link-4" href="" ng:model="xx" ng:click="value = 4">anchor</a> (link, don't reload)<br />
<a id="link-5" ng:model="xxx" ng:click="value = 5">anchor</a> (no link)<br />
<a id="link-6" ng:href="#/{{value}}">link</a> (link, change hash)
</body>
</html>
-18
View File
@@ -1,18 +0,0 @@
<!DOCTYPE HTML>
<html xmlns:ng="http://angularjs.org">
<script type="text/javascript" src="../build/angular.js" ng:autobind></script>
<script type="text/javascript">
function Cntl($route) {
$route.when('/item1', {});
$route.when('/item2', {});
$route.onChange(function() {
alert('change');
});
}
Cntl.$inject = ['$route'];
</script>
<body ng:controller="Ctrl">
<a href="#/item1">test</a>
<a href="#/item2">test</a>
</body>
</html>
-24
View File
@@ -1,24 +0,0 @@
<!DOCTYPE html>
<html xmlns:ng="http://angularjs.org" xmlns:my="http://mynamespace.org">
<head>
<style>
my\:time {color:#00f;display:block;border:1px solid #ccc;background-color:#ddd;}
</style>
<script src="../build/angular.js" ng:autobind></script>
<script>
angular.widget('my:time', function(compileElement){
compileElement.css('display', 'block');
return function(linkElement) {
function update() {
linkElement.text('Current time is: ' + new Date());
setTimeout(update, 1000);
}
update();
};
});
</script>
</head>
<body>
<my:time></my:time>
</body>
</html>
-9
View File
@@ -1,9 +0,0 @@
<!DOCTYPE HTML>
<html xmlns:ng="http://angularjs.org">
<head>
<script type="text/javascript" src="../src/angular-bootstrap.js" ng:autobind></script>
</head>
<body ng:init="$window.$root = this; data = [{foo: 'foo'},{bar: 'bar'}]">
<ng:include src="'ng_include_this.partial'" scope="this"/>
</body>
</html>
-1
View File
@@ -1 +0,0 @@
included HTML. eval count: {{c=c+1}}
-30
View File
@@ -1,30 +0,0 @@
<!DOCTYPE HTML>
<html xmlns:ng="http://angularjs.org">
<head>
<script type="text/javascript" src="../src/angular-bootstrap.js" ng:autobind></script>
</script>
<script type="text/javascript">
angular.module.ng('myService', function($resource){
this.myData = $resource('resource_json_date.json');
}, {$inject:['$resource'], $creation:'eager'});
/* The Controller object */
MyController = function() {
this.inlineData = angular.fromJson('{reportDate:"2010-10-13T17:37:00Z"}');
this.jsonData = this.myData.get();
};
</script>
</head>
<body ng:controller="MyController" ng:init="$window.$root = this">
<h3>This data is loaded with angular.fromJson:</h3>
{{ inlineData.reportDate | date }}
<hr/>
<h3>This data is loaded from a resource using a service:</h3>
<p>Name: {{ jsonData.name }}</p>
<p>Parsed date: {{ jsonData.reportDate }} (A date should be displayed here)</p>
</body>
</html>
-1
View File
@@ -1 +0,0 @@
{reportDate:"2010-10-13T17:37:00Z", name:"camilo"}
-8
View File
@@ -1,8 +0,0 @@
<!DOCTYPE HTML>
<html xmlns:ng="http://angularjs.org">
<script type="text/javascript" src="../src/angular-bootstrap.js" ng:autobind></script>
<body>
<textarea ng:model="html" rows="10" cols="100"></textarea>
<div>{{html|html}}</div>
</body>
</html>
+6 -4
View File
@@ -621,13 +621,15 @@ function equals(o1, o2) {
if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;
keySet = {};
for(key in o1) {
if (key.charAt(0) !== '$' && !isFunction(o1[key]) && !equals(o1[key], o2[key])) {
return false;
}
if (key.charAt(0) === '$' || isFunction(o1[key])) continue;
if (!equals(o1[key], o2[key])) return false;
keySet[key] = true;
}
for(key in o2) {
if (!keySet[key] && key.charAt(0) !== '$' && !isFunction(o2[key])) return false;
if (!keySet[key] &&
key.charAt(0) !== '$' &&
o2[key] !== undefined &&
!isFunction(o2[key])) return false;
}
return true;
}
+7 -8
View File
@@ -410,9 +410,10 @@ function createInjector(modulesToLoad) {
decorator: decorator
}
},
providerInjector = createInternalInjector(providerCache, function() {
throw Error("Unknown provider: " + path.join(' <- '));
}),
providerInjector = (providerCache.$injector =
createInternalInjector(providerCache, function() {
throw Error("Unknown provider: " + path.join(' <- '));
})),
instanceCache = {},
instanceInjector = (instanceCache.$injector =
createInternalInjector(instanceCache, function(servicename) {
@@ -440,7 +441,7 @@ function createInjector(modulesToLoad) {
}
function provider(name, provider_) {
if (isFunction(provider_)) {
if (isFunction(provider_) || isArray(provider_)) {
provider_ = providerInjector.instantiate(provider_);
}
if (!provider_.$get) {
@@ -489,9 +490,7 @@ function createInjector(modulesToLoad) {
try {
for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {
var invokeArgs = invokeQueue[i],
provider = invokeArgs[0] == '$injector'
? providerInjector
: providerInjector.get(invokeArgs[0]);
provider = providerInjector.get(invokeArgs[0]);
provider[invokeArgs[1]].apply(provider, invokeArgs[2]);
}
@@ -557,7 +556,7 @@ function createInjector(modulesToLoad) {
args.push(
locals && locals.hasOwnProperty(key)
? locals[key]
: getService(key, path)
: getService(key)
);
}
if (!fn.$inject) {
+4 -4
View File
@@ -4,10 +4,10 @@ var directive = {};
var service = { value: {} };
var DEPENDENCIES = {
'angular.js': 'http://code.angularjs.org/angular-' + angular.version.full + '.min.js',
'angular-resource.js': 'http://code.angularjs.org/angular-resource-' + angular.version.full + '.min.js',
'angular-sanitize.js': 'http://code.angularjs.org/angular-sanitize-' + angular.version.full + '.min.js',
'angular-cookies.js': 'http://code.angularjs.org/angular-cookies-' + angular.version.full + '.min.js'
'angular.js': 'http://code.angularjs.org/' + angular.version.full + 'angular.min.js',
'angular-resource.js': 'http://code.angularjs.org/' + angular.version.full + 'angular-resource.min.js',
'angular-sanitize.js': 'http://code.angularjs.org/' + angular.version.full + 'angular-sanitize.min.js',
'angular-cookies.js': 'http://code.angularjs.org/' + angular.version.full + 'angular-cookies.min.js'
};
+17 -7
View File
@@ -59,7 +59,7 @@
* - [val()](http://api.jquery.com/val/)
* - [wrap()](http://api.jquery.com/wrap/)
*
* ## In addtion to the above, Angular privides an additional method to both jQuery and jQuery lite:
* ## In addtion to the above, Angular provides additional methods to both jQuery and jQuery lite:
*
* - `controller(name)` - retrieves the controller of the current element or its parent. By default
* retrieves controller associated with the `ngController` directive. If `name` is provided as
@@ -353,11 +353,11 @@ var JQLitePrototype = JQLite.prototype = {
// value on get.
//////////////////////////////////////////
var BOOLEAN_ATTR = {};
forEach('multiple,selected,checked,disabled,readOnly,required'.split(','), function(value) {
forEach('multiple,selected,checked,disabled,readOnly,required,open'.split(','), function(value) {
BOOLEAN_ATTR[lowercase(value)] = value;
});
var BOOLEAN_ELEMENTS = {};
forEach('input,select,option,textarea,button,form'.split(','), function(value) {
forEach('input,select,option,textarea,button,form,details'.split(','), function(value) {
BOOLEAN_ELEMENTS[uppercase(value)] = true;
});
@@ -647,20 +647,21 @@ forEach({
children: function(element) {
var children = [];
forEach(element.childNodes, function(element){
if (element.nodeName != '#text')
if (element.nodeType === 1)
children.push(element);
});
return children;
},
contents: function(element) {
return element.childNodes;
return element.childNodes || [];
},
append: function(element, node) {
forEach(new JQLite(node), function(child){
if (element.nodeType === 1)
if (element.nodeType === 1 || element.nodeType === 11) {
element.appendChild(child);
}
});
},
@@ -717,7 +718,16 @@ forEach({
},
next: function(element) {
return element.nextSibling;
if (element.nextElementSibling) {
return element.nextElementSibling;
}
// IE8 doesn't have nextElementSibling
var elm = element.nextSibling;
while (elm != null && elm.nodeType !== 1) {
elm = elm.nextSibling;
}
return elm;
},
find: function(element, selector) {
+1 -1
View File
@@ -53,7 +53,7 @@ function $AnchorScrollProvider() {
}
// does not scroll when user clicks on anchor link that is currently on
// (no url change, no $locaiton.hash() change), browser native does scroll
// (no url change, no $location.hash() change), browser native does scroll
if (autoScrollingEnabled) {
$rootScope.$watch(function autoScrollWatch() {return $location.hash();},
function autoScrollWatchAction() {
+5 -4
View File
@@ -276,14 +276,15 @@ function Browser(window, document, $log, $sniffer) {
} else {
if (isString(value)) {
cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) + ';path=' + cookiePath).length + 1;
// per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:
// - 300 cookies
// - 20 cookies per unique domain
// - 4096 bytes per cookie
if (cookieLength > 4096) {
$log.warn("Cookie '"+ name +"' possibly not set or overflowed because it was too large ("+
cookieLength + " > 4096 bytes)!");
}
if (lastCookies.length > 20) {
$log.warn("Cookie '"+ name +"' possibly not set or overflowed because too many cookies " +
"were already set (" + lastCookies.length + " > 20 )");
}
}
}
} else {
+3 -1
View File
@@ -14,7 +14,7 @@
* @returns {object} Newly created cache object with the following set of methods:
*
* - `{object}` `info()` — Returns id, size, and options of cache.
* - `{void}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache.
* - `{{*}}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache and returns it.
* - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss.
* - `{void}` `remove({string} key)` — Removes a key-value pair from the cache.
* - `{void}` `removeAll()` — Removes all cached values.
@@ -53,6 +53,8 @@ function $CacheFactoryProvider() {
if (size > capacity) {
this.remove(staleEnd.key);
}
return value;
},
+58 -52
View File
@@ -318,7 +318,7 @@ function $CompileProvider($provide) {
// We can not compile top level text elements since text nodes can be merged and we will
// not be able to attach scope data to them, so we will wrap them in <span>
forEach($compileNodes, function(node, index){
if (node.nodeType == 3 /* text node */) {
if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\S+/) /* non-empty */ ) {
$compileNodes[index] = jqLite(node).wrap('<span></span>').parent()[0];
}
});
@@ -367,68 +367,74 @@ function $CompileProvider($provide) {
* @returns {?function} A composite linking function of all of the matched directives or null.
*/
function compileNodes(nodeList, transcludeFn, $rootElement, maxPriority) {
var linkFns = [],
nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;
var linkFns = [],
nodeLinkFn, childLinkFn, directives, attrs, linkFnFound;
for(var i = 0; i < nodeList.length; i++) {
attrs = new Attributes();
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.
directives = collectDirectives(nodeList[i], [], attrs, maxPriority);
// we must always refer to nodeList[i] since the nodes can be replaced underneath us.
directives = collectDirectives(nodeList[i], [], attrs, maxPriority);
nodeLinkFn = (directives.length)
? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)
: null;
nodeLinkFn = (directives.length)
? applyDirectivesToNode(directives, nodeList[i], attrs, transcludeFn, $rootElement)
: null;
childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)
? null
: compileNodes(nodeList[i].childNodes,
nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);
childLinkFn = (nodeLinkFn && nodeLinkFn.terminal || !nodeList[i].childNodes.length)
? null
: compileNodes(nodeList[i].childNodes,
nodeLinkFn ? nodeLinkFn.transclude : transcludeFn);
linkFns.push(nodeLinkFn);
linkFns.push(childLinkFn);
linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);
}
linkFns.push(nodeLinkFn);
linkFns.push(childLinkFn);
linkFnFound = (linkFnFound || nodeLinkFn || childLinkFn);
}
// return a linking function if we have found anything, null otherwise
return linkFnFound ? compositeLinkFn : null;
// return a linking function if we have found anything, null otherwise
return linkFnFound ? compositeLinkFn : null;
function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {
var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn;
function compositeLinkFn(scope, nodeList, $rootElement, boundTranscludeFn) {
var nodeLinkFn, childLinkFn, node, childScope, childTranscludeFn, i, ii, n;
for(var i = 0, n = 0, ii = linkFns.length; i < ii; n++) {
node = nodeList[n];
nodeLinkFn = linkFns[i++];
childLinkFn = linkFns[i++];
// 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]);
}
if (nodeLinkFn) {
if (nodeLinkFn.scope) {
childScope = scope.$new(isObject(nodeLinkFn.scope));
jqLite(node).data('$scope', childScope);
} else {
childScope = scope;
}
childTranscludeFn = nodeLinkFn.transclude;
if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {
nodeLinkFn(childLinkFn, childScope, node, $rootElement,
(function(transcludeFn) {
return function(cloneFn) {
var transcludeScope = scope.$new();
for(i = 0, n = 0, ii = linkFns.length; i < ii; n++) {
node = stableNodeList[n];
nodeLinkFn = linkFns[i++];
childLinkFn = linkFns[i++];
return transcludeFn(transcludeScope, cloneFn).
bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));
if (nodeLinkFn) {
if (nodeLinkFn.scope) {
childScope = scope.$new(isObject(nodeLinkFn.scope));
jqLite(node).data('$scope', childScope);
} else {
childScope = scope;
}
childTranscludeFn = nodeLinkFn.transclude;
if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {
nodeLinkFn(childLinkFn, childScope, node, $rootElement,
(function(transcludeFn) {
return function(cloneFn) {
var transcludeScope = scope.$new();
return transcludeFn(transcludeScope, cloneFn).
bind('$destroy', bind(transcludeScope, transcludeScope.$destroy));
};
})(childTranscludeFn || transcludeFn)
);
} else {
nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);
}
} else if (childLinkFn) {
childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);
}
}
}
}
);
} else {
nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);
}
} else if (childLinkFn) {
childLinkFn(scope, node.childNodes, undefined, boundTranscludeFn);
}
}
}
}
/**
@@ -575,7 +581,7 @@ function $CompileProvider($provide) {
if (directiveValue == 'element') {
$template = jqLite(compileNode);
$compileNode = templateAttrs.$$element =
jqLite('<!-- ' + directiveName + ': ' + templateAttrs[directiveName] + ' -->');
jqLite(document.createComment(' ' + directiveName + ': ' + templateAttrs[directiveName] + ' '));
compileNode = $compileNode[0];
replaceWith($rootElement, jqLite($template[0]), compileNode);
childTranscludeFn = compile($template, transcludeFn, terminalPriority);
-1
View File
@@ -27,7 +27,6 @@ var htmlAnchorDirective = valueFn({
// if we have no href url, then don't navigate anywhere.
if (!element.attr('href')) {
event.preventDefault();
return false; // Needed for opera
}
});
}
+31
View File
@@ -272,6 +272,37 @@
* @param {string} expression Angular expression that will be evaluated.
*/
/**
* @ngdoc directive
* @name ng.directive:ngOpen
* @restrict A
*
* @description
* The HTML specs do not require browsers to preserve the special attributes such as open.
* (The presence of them means true and absence means false)
* This prevents the angular compiler from correctly retrieving the binding expression.
* To solve this problem, we introduce the `ngOpen` directive.
*
* @example
<doc:example>
<doc:source>
Check me check multiple: <input type="checkbox" ng-model="open"><br/>
<details id="details" ng-open="open">
<summary>Show/Hide me</summary>
</details>
</doc:source>
<doc:scenario>
it('should toggle open', function() {
expect(element('#details').prop('open')).toBeFalsy();
input('open').check();
expect(element('#details').prop('open')).toBeTruthy();
});
</doc:scenario>
</doc:example>
*
* @element DETAILS
* @param {string} expression Angular expression that will be evaluated.
*/
var ngAttributeAliasDirectives = {};
+36 -7
View File
@@ -5,7 +5,8 @@ var nullFormCtrl = {
$addControl: noop,
$removeControl: noop,
$setValidity: noop,
$setDirty: noop
$setDirty: noop,
$setPristine: noop
};
/**
@@ -14,13 +15,13 @@ var nullFormCtrl = {
*
* @property {boolean} $pristine True if user has not interacted with the form yet.
* @property {boolean} $dirty True if user has already interacted with the form.
* @property {boolean} $valid True if all of the containg forms and controls are valid.
* @property {boolean} $valid True if all of the containing forms and controls are valid.
* @property {boolean} $invalid True if at least one containing control or form is invalid.
*
* @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`),
* - 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.
*
* @description
@@ -37,7 +38,8 @@ function FormController(element, attrs) {
var form = this,
parentForm = element.parent().controller('form') || nullFormCtrl,
invalidCount = 0, // used to easily determine if we are valid
errors = form.$error = {};
errors = form.$error = {},
controls = [];
// init state
form.$name = attrs.name;
@@ -61,6 +63,8 @@ function FormController(element, attrs) {
}
form.$addControl = function(control) {
controls.push(control);
if (control.$name && !form.hasOwnProperty(control.$name)) {
form[control.$name] = control;
}
@@ -73,6 +77,8 @@ function FormController(element, attrs) {
forEach(errors, function(queue, validationToken) {
form.$setValidity(validationToken, true, control);
});
arrayRemove(controls, control);
};
form.$setValidity = function(validationToken, isValid, control) {
@@ -120,6 +126,29 @@ function FormController(element, attrs) {
parentForm.$setDirty();
};
/**
* @ngdoc function
* @name ng.directive:form.FormController#$setPristine
* @methodOf ng.directive:form.FormController
*
* @description
* Sets the form to its pristine state.
*
* This method can be called to remove the 'ng-dirty' class and set the form to its pristine
* state (ng-pristine class). This method will also propagate to all the controls contained
* in this form.
*
* Setting a form back to a pristine state is often useful when we want to 'reuse' a form after
* saving or resetting it.
*/
form.$setPristine = function () {
element.removeClass(DIRTY_CLASS).addClass(PRISTINE_CLASS);
form.$dirty = false;
form.$pristine = true;
forEach(controls, function(control) {
control.$setPristine();
});
};
}
@@ -133,7 +162,7 @@ function FormController(element, attrs) {
* does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a
* sub-group of controls needs to be determined.
*
* @param {string=} ngForm|name Name of the form. If specified, the form controller will be published into
* @param {string=} name|ngForm Name of the form. If specified, the form controller will be published into
* related scope, under this name.
*
*/
@@ -206,12 +235,12 @@ function FormController(element, attrs) {
</script>
<form name="myForm" ng-controller="Ctrl">
userType: <input name="input" ng-model="userType" required>
<span class="error" ng-show="myForm.input.$error.REQUIRED">Required!</span><br>
<span class="error" ng-show="myForm.input.$error.required">Required!</span><br>
<tt>userType = {{userType}}</tt><br>
<tt>myForm.input.$valid = {{myForm.input.$valid}}</tt><br>
<tt>myForm.input.$error = {{myForm.input.$error}}</tt><br>
<tt>myForm.$valid = {{myForm.$valid}}</tt><br>
<tt>myForm.$error.REQUIRED = {{!!myForm.$error.REQUIRED}}</tt><br>
<tt>myForm.$error.required = {{!!myForm.$error.required}}</tt><br>
</form>
</doc:source>
<doc:scenario>
+34 -3
View File
@@ -28,6 +28,8 @@ var inputType = {
* patterns defined as scope expressions.
* @param {string=} ngChange Angular expression to be executed when input changes due to user
* interaction with the input element.
* @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trimming the
* input.
*
* @example
<doc:example>
@@ -35,12 +37,12 @@ var inputType = {
<script>
function Ctrl($scope) {
$scope.text = 'guest';
$scope.word = /^\w*$/;
$scope.word = /^\s*\w*\s*$/;
}
</script>
<form name="myForm" ng-controller="Ctrl">
Single word: <input type="text" name="input" ng-model="text"
ng-pattern="word" required>
ng-pattern="word" required ng-trim="false">
<span class="error" ng-show="myForm.input.$error.required">
Required!</span>
<span class="error" ng-show="myForm.input.$error.pattern">
@@ -69,6 +71,12 @@ var inputType = {
input('text').enter('hello world');
expect(binding('myForm.input.$valid')).toEqual('false');
});
it('should not be trimmed', function() {
input('text').enter('untrimmed ');
expect(binding('text')).toEqual('untrimmed ');
expect(binding('myForm.input.$valid')).toEqual('true');
});
</doc:scenario>
</doc:example>
*/
@@ -382,7 +390,14 @@ function isEmpty(value) {
function textInputType(scope, element, attr, ctrl, $sniffer, $browser) {
var listener = function() {
var value = trim(element.val());
var value = element.val();
// By default we will trim the value
// If the attribute ng-trim exists we will avoid trimming
// e.g. <input ng-model="foo" ng-trim="false">
if (toBoolean(attr.ngTrim || 'T')) {
value = trim(value);
}
if (ctrl.$viewValue !== value) {
scope.$apply(function() {
@@ -963,6 +978,22 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
parentForm.$setValidity(validationErrorKey, isValid, this);
};
/**
* @ngdoc function
* @name ng.directive:ngModel.NgModelController#$setPristine
* @methodOf ng.directive:ngModel.NgModelController
*
* @description
* Sets the control to its pristine state.
*
* This method can be called to remove the 'ng-dirty' class and set the control to its pristine
* state (ng-pristine class).
*/
this.$setPristine = function () {
this.$dirty = false;
this.$pristine = true;
$element.removeClass(DIRTY_CLASS).addClass(PRISTINE_CLASS);
};
/**
* @ngdoc function
+33 -1
View File
@@ -37,7 +37,7 @@
*/
var ngEventDirectives = {};
forEach(
'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave'.split(' '),
'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup'.split(' '),
function(name) {
var directiveName = directiveNormalize('ng-' + name);
ngEventDirectives[directiveName] = ['$parse', function($parse) {
@@ -164,6 +164,38 @@ forEach(
*/
/**
* @ngdoc directive
* @name ng.directive:ngKeydown
*
* @description
* Specify custom behavior on keydown event.
*
* @element ANY
* @param {expression} ngKeydown {@link guide/expression Expression} to evaluate upon
* keydown. (Event object is available as `$event` and can be interrogated for keyCode, altKey, etc.)
*
* @example
* See {@link ng.directive:ngClick ngClick}
*/
/**
* @ngdoc directive
* @name ng.directive:ngKeyup
*
* @description
* Specify custom behavior on keyup event.
*
* @element ANY
* @param {expression} ngKeyup {@link guide/expression Expression} to evaluate upon
* keyup. (Event object is available as `$event` and can be interrogated for keyCode, altKey, etc.)
*
* @example
* See {@link ng.directive:ngClick ngClick}
*/
/**
* @ngdoc directive
* @name ng.directive:ngSubmit
+10 -5
View File
@@ -92,14 +92,17 @@ var ngRepeatDirective = ngDirective({
scope.$watch(function ngRepeatWatch(scope){
var index, length,
collection = scope.$eval(rhs),
collectionLength = size(collection, true),
childScope,
cursor = iterStartElement, // current position of the node
// Same as lastOrder but it has the current state. It will become the
// lastOrder on the next iteration.
nextOrder = new HashQueueMap(),
arrayLength,
childScope,
key, value, // key/value of iteration
array, last, // last object information {scope, element, index}
cursor = iterStartElement; // current position of the node
array,
last; // last object information {scope, element, index}
if (!isArray(collection)) {
// if object, extract keys, sort them and use to determine order of iteration over obj props
@@ -114,6 +117,8 @@ var ngRepeatDirective = ngDirective({
array = collection || [];
}
arrayLength = array.length;
// we are not using forEach for perf reasons (trying to avoid #call)
for (index = 0, length = array.length; index < length; index++) {
key = (collection === array) ? index : array[index];
@@ -149,7 +154,7 @@ var ngRepeatDirective = ngDirective({
childScope.$index = index;
childScope.$first = (index === 0);
childScope.$last = (index === (collectionLength - 1));
childScope.$last = (index === (arrayLength - 1));
childScope.$middle = !(childScope.$first || childScope.$last);
if (!last) {
+31 -30
View File
@@ -62,51 +62,52 @@
var NG_SWITCH = 'ng-switch';
var ngSwitchDirective = valueFn({
restrict: 'EA',
compile: function(element, attr) {
require: 'ngSwitch',
controller: function ngSwitchController() {
this.cases = {};
},
link: function(scope, element, attr, ctrl) {
var watchExpr = attr.ngSwitch || attr.on,
cases = {};
selectedTransclude,
selectedElement,
selectedScope;
element.data(NG_SWITCH, cases);
return function(scope, element){
var selectedTransclude,
selectedElement,
selectedScope;
scope.$watch(watchExpr, function ngSwitchWatchAction(value) {
if (selectedElement) {
selectedScope.$destroy();
selectedElement.remove();
selectedElement = selectedScope = null;
}
if ((selectedTransclude = cases['!' + value] || cases['?'])) {
scope.$eval(attr.change);
selectedScope = scope.$new();
selectedTransclude(selectedScope, function(caseElement) {
selectedElement = caseElement;
element.append(caseElement);
});
}
});
};
scope.$watch(watchExpr, function ngSwitchWatchAction(value) {
if (selectedElement) {
selectedScope.$destroy();
selectedElement.remove();
selectedElement = selectedScope = null;
}
if ((selectedTransclude = ctrl.cases['!' + value] || ctrl.cases['?'])) {
scope.$eval(attr.change);
selectedScope = scope.$new();
selectedTransclude(selectedScope, function(caseElement) {
selectedElement = caseElement;
element.append(caseElement);
});
}
});
}
});
var ngSwitchWhenDirective = ngDirective({
transclude: 'element',
priority: 500,
require: '^ngSwitch',
compile: function(element, attrs, transclude) {
var cases = element.inheritedData(NG_SWITCH);
assertArg(cases);
cases['!' + attrs.ngSwitchWhen] = transclude;
return function(scope, element, attr, ctrl) {
ctrl.cases['!' + attrs.ngSwitchWhen] = transclude;
};
}
});
var ngSwitchDefaultDirective = ngDirective({
transclude: 'element',
priority: 500,
require: '^ngSwitch',
compile: function(element, attrs, transclude) {
var cases = element.inheritedData(NG_SWITCH);
assertArg(cases);
cases['?'] = transclude;
return function(scope, element, attr, ctrl) {
ctrl.cases['?'] = transclude;
};
}
});
+1 -1
View File
@@ -28,7 +28,7 @@
<hr />
<pre>$location.path() = {{$location.path()}}</pre>
<pre>$route.current.template = {{$route.current.template}}</pre>
<pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>
<pre>$route.current.params = {{$route.current.params}}</pre>
<pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>
<pre>$routeParams = {{$routeParams}}</pre>
+2 -2
View File
@@ -265,7 +265,7 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
var lastView;
ctrl.$render = function() {
var items = new HashMap(ctrl.$viewValue);
forEach(selectElement.children(), function(option) {
forEach(selectElement.find('option'), function(option) {
option.selected = isDefined(items.get(option.value));
});
};
@@ -282,7 +282,7 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
selectElement.bind('change', function() {
scope.$apply(function() {
var array = [];
forEach(selectElement.children(), function(option) {
forEach(selectElement.find('option'), function(option) {
if (option.selected) {
array.push(option.value);
}
+2 -1
View File
@@ -11,11 +11,12 @@
* the browser console.
*
* In unit tests, if `angular-mocks.js` is loaded, this service is overridden by
* {@link ngMock.$exceptionHandler mock $exceptionHandler}
* {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing.
*
* @param {Error} exception Exception associated with the error.
* @param {string=} cause optional information about the context in which
* the error was thrown.
*
*/
function $ExceptionHandlerProvider() {
this.$get = ['$log', function($log){
+8 -4
View File
@@ -330,18 +330,22 @@ function dateFilter($locale) {
var R_ISO8601_STR = /^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/;
function jsonStringToDate(string){
// 1 2 3 4 5 6 7 8 9 10 11
function jsonStringToDate(string) {
var match;
if (match = string.match(R_ISO8601_STR)) {
var date = new Date(0),
tzHour = 0,
tzMin = 0;
tzMin = 0,
dateSetter = match[8] ? date.setUTCFullYear : date.setFullYear,
timeSetter = match[8] ? date.setUTCHours : date.setHours;
if (match[9]) {
tzHour = int(match[9] + match[10]);
tzMin = int(match[9] + match[11]);
}
date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3]));
date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));
dateSetter.call(date, int(match[1]), int(match[2]) - 1, int(match[3]));
timeSetter.call(date, int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0));
return date;
}
return string;
+50 -33
View File
@@ -6,20 +6,20 @@
* @function
*
* @description
* Creates a new array containing only a specified number of elements in an array. The elements
* are taken from either the beginning or the end of the source array, as specified by the
* value and sign (positive or negative) of `limit`.
* Creates a new array or string containing only a specified number of elements. The elements
* are taken from either the beginning or the end of the source array or string, as specified by
* the value and sign (positive or negative) of `limit`.
*
* Note: This function is used to augment the `Array` type in Angular expressions. See
* {@link ng.$filter} for more information about Angular arrays.
*
* @param {Array} array Source array to be limited.
* @param {string|Number} limit The length of the returned array. If the `limit` number is
* positive, `limit` number of items from the beginning of the source array are copied.
* If the number is negative, `limit` number of items from the end of the source array are
* copied. The `limit` will be trimmed if it exceeds `array.length`
* @returns {Array} A new sub-array of length `limit` or less if input array had less than `limit`
* elements.
* @param {Array|string} input Source array or string to be limited.
* @param {string|number} limit The length of the returned array or string. If the `limit` number
* is positive, `limit` number of items from the beginning of the source array/string are copied.
* If the number is negative, `limit` number of items from the end of the source array/string
* are copied. The `limit` will be trimmed if it exceeds `array.length`
* @returns {Array|string} A new sub-array or substring of length `limit` or less if input array
* had less than `limit` elements.
*
* @example
<doc:example>
@@ -27,59 +27,76 @@
<script>
function Ctrl($scope) {
$scope.numbers = [1,2,3,4,5,6,7,8,9];
$scope.limit = 3;
$scope.letters = "abcdefghi";
$scope.numLimit = 3;
$scope.letterLimit = 3;
}
</script>
<div ng-controller="Ctrl">
Limit {{numbers}} to: <input type="integer" ng-model="limit">
<p>Output: {{ numbers | limitTo:limit }}</p>
Limit {{numbers}} to: <input type="integer" ng-model="numLimit">
<p>Output numbers: {{ numbers | limitTo:numLimit }}</p>
Limit {{letters}} to: <input type="integer" ng-model="letterLimit">
<p>Output letters: {{ letters | limitTo:letterLimit }}</p>
</div>
</doc:source>
<doc:scenario>
it('should limit the numer array to first three items', function() {
expect(element('.doc-example-live input[ng-model=limit]').val()).toBe('3');
expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3]');
it('should limit the number array to first three items', function() {
expect(element('.doc-example-live input[ng-model=numLimit]').val()).toBe('3');
expect(element('.doc-example-live input[ng-model=letterLimit]').val()).toBe('3');
expect(binding('numbers | limitTo:numLimit')).toEqual('[1,2,3]');
expect(binding('letters | limitTo:letterLimit')).toEqual('abc');
});
it('should update the output when -3 is entered', function() {
input('limit').enter(-3);
expect(binding('numbers | limitTo:limit')).toEqual('[7,8,9]');
input('numLimit').enter(-3);
input('letterLimit').enter(-3);
expect(binding('numbers | limitTo:numLimit')).toEqual('[7,8,9]');
expect(binding('letters | limitTo:letterLimit')).toEqual('ghi');
});
it('should not exceed the maximum size of input array', function() {
input('limit').enter(100);
expect(binding('numbers | limitTo:limit')).toEqual('[1,2,3,4,5,6,7,8,9]');
input('numLimit').enter(100);
input('letterLimit').enter(100);
expect(binding('numbers | limitTo:numLimit')).toEqual('[1,2,3,4,5,6,7,8,9]');
expect(binding('letters | limitTo:letterLimit')).toEqual('abcdefghi');
});
</doc:scenario>
</doc:example>
*/
function limitToFilter(){
return function(array, limit) {
if (!(array instanceof Array)) return array;
return function(input, limit) {
if (!isArray(input) && !isString(input)) return input;
limit = int(limit);
if (isString(input)) {
//NaN check on limit
if (limit) {
return limit >= 0 ? input.slice(0, limit) : input.slice(limit, input.length);
} else {
return "";
}
}
var out = [],
i, n;
// check that array is iterable
if (!array || !(array instanceof Array))
return out;
// if abs(limit) exceeds maximum length, trim it
if (limit > array.length)
limit = array.length;
else if (limit < -array.length)
limit = -array.length;
if (limit > input.length)
limit = input.length;
else if (limit < -input.length)
limit = -input.length;
if (limit > 0) {
i = 0;
n = limit;
} else {
i = array.length + limit;
n = array.length;
i = input.length + limit;
n = input.length;
}
for (; i<n; i++) {
out.push(array[i]);
out.push(input[i]);
}
return out;
+71 -20
View File
@@ -29,6 +29,43 @@ function parseHeaders(headers) {
}
var IS_SAME_DOMAIN_URL_MATCH = /^(([^:]+):)?\/\/(\w+:{0,1}\w*@)?([\w\.-]*)?(:([0-9]+))?(.*)$/;
/**
* Parse a request and location URL and determine whether this is a same-domain request.
*
* @param {string} requestUrl The url of the request.
* @param {string} locationUrl The current browser location url.
* @returns {boolean} Whether the request is for the same domain.
*/
function isSameDomain(requestUrl, locationUrl) {
var match = IS_SAME_DOMAIN_URL_MATCH.exec(requestUrl);
// if requestUrl is relative, the regex does not match.
if (match == null) return true;
var domain1 = {
protocol: match[2],
host: match[4],
port: int(match[6]) || DEFAULT_PORTS[match[2]] || null,
// IE8 sets unmatched groups to '' instead of undefined.
relativeProtocol: match[2] === undefined || match[2] === ''
};
match = URL_MATCH.exec(locationUrl);
var domain2 = {
protocol: match[1],
host: match[3],
port: int(match[5]) || DEFAULT_PORTS[match[1]] || null
};
return (domain1.protocol == domain2.protocol || domain1.relativeProtocol) &&
domain1.host == domain2.host &&
(domain1.port == domain2.port || (domain1.relativeProtocol &&
domain2.port == DEFAULT_PORTS[domain2.protocol]));
}
/**
* Returns a function that provides access to parsed headers.
*
@@ -88,7 +125,7 @@ function $HttpProvider() {
JSON_END = /[\}\]]\s*$/,
PROTECTION_PREFIX = /^\)\]\}',?\n/;
var $config = this.defaults = {
var defaults = this.defaults = {
// transform incoming response data
transformResponse: [function(data) {
if (isString(data)) {
@@ -108,8 +145,7 @@ function $HttpProvider() {
// default headers
headers: {
common: {
'Accept': 'application/json, text/plain, */*',
'X-Requested-With': 'XMLHttpRequest'
'Accept': 'application/json, text/plain, */*'
},
post: {'Content-Type': 'application/json;charset=utf-8'},
put: {'Content-Type': 'application/json;charset=utf-8'}
@@ -136,7 +172,7 @@ function $HttpProvider() {
/**
* @ngdoc function
* @name ng.$http
* @requires $httpBacked
* @requires $httpBackend
* @requires $browser
* @requires $cacheFactory
* @requires $rootScope
@@ -172,8 +208,7 @@ function $HttpProvider() {
* }).
* error(function(data, status, headers, config) {
* // called asynchronously if an error occurs
* // or server returns response with status
* // code outside of the <200, 400) range
* // or server returns response with an error status.
* });
* </pre>
*
@@ -182,6 +217,10 @@ function $HttpProvider() {
* an object representing the response. See the api signature and type info below for more
* details.
*
* A response status code that falls in the [200, 300) range is considered a success status and
* will result in the success callback being called. Note that if the response is a redirect,
* XMLHttpRequest will transparently follow it, meaning that the error callback will not be
* called for such responses.
*
* # Shortcut methods
*
@@ -212,7 +251,6 @@ function $HttpProvider() {
*
* - `$httpProvider.defaults.headers.common` (headers that are common for all requests):
* - `Accept: application/json, text/plain, * / *`
* - `X-Requested-With: XMLHttpRequest`
* - `$httpProvider.defaults.headers.post`: (header defaults for HTTP POST requests)
* - `Content-Type: application/json`
* - `$httpProvider.defaults.headers.put` (header defaults for HTTP PUT requests)
@@ -347,7 +385,7 @@ function $HttpProvider() {
* to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie
* called `XSRF-TOKEN` and sets it as the HTTP header `X-XSRF-TOKEN`. Since only JavaScript that
* runs on your domain could read the cookie, your server can be assured that the XHR came from
* JavaScript running on your domain.
* JavaScript running on your domain. The header will not be set for cross-domain requests.
*
* To take advantage of this, your server needs to set a token in a JavaScript readable session
* cookie called `XSRF-TOKEN` on first HTTP GET request. On subsequent non-GET requests the
@@ -381,6 +419,8 @@ function $HttpProvider() {
* - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the
* XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5
* requests with credentials} for more information.
* - **responseType** - `{string}` - see {@link
* https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#responseType requestType}.
*
* @returns {HttpPromise} Returns a {@link ng.$q promise} object with the
* standard `then` method and two http specific methods: `success` and `error`. The `then`
@@ -473,10 +513,12 @@ function $HttpProvider() {
function $http(config) {
config.method = uppercase(config.method);
var reqTransformFn = config.transformRequest || $config.transformRequest,
respTransformFn = config.transformResponse || $config.transformResponse,
defHeaders = $config.headers,
reqHeaders = extend({'X-XSRF-TOKEN': $browser.cookies()['XSRF-TOKEN']},
var reqTransformFn = config.transformRequest || defaults.transformRequest,
respTransformFn = config.transformResponse || defaults.transformResponse,
defHeaders = defaults.headers,
xsrfToken = isSameDomain(config.url, $browser.url()) ?
$browser.cookies()['XSRF-TOKEN'] : undefined,
reqHeaders = extend({'X-XSRF-TOKEN': xsrfToken},
defHeaders.common, defHeaders[lowercase(config.method)], config.headers),
reqData = transformData(config.data, headersGetter(reqHeaders), reqTransformFn),
promise;
@@ -486,6 +528,10 @@ function $HttpProvider() {
delete reqHeaders['Content-Type'];
}
if (isUndefined(config.withCredentials) && !isUndefined(defaults.withCredentials)) {
config.withCredentials = defaults.withCredentials;
}
// send request
promise = sendReq(config, reqData, reqHeaders);
@@ -617,11 +663,11 @@ function $HttpProvider() {
*
* @description
* Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of
* default headers as well as request and response transformations.
* default headers, withCredentials as well as request and response transformations.
*
* See "Setting HTTP Headers" and "Transforming Requests and Responses" sections above.
*/
$http.defaults = $config;
$http.defaults = defaults;
return $http;
@@ -656,7 +702,7 @@ function $HttpProvider() {
* Makes the request
*
* !!! ACCESSES CLOSURE VARS:
* $httpBackend, $config, $log, $rootScope, defaultCache, $http.pendingRequests
* $httpBackend, defaults, $log, $rootScope, defaultCache, $http.pendingRequests
*/
function sendReq(config, reqData, reqHeaders) {
var deferred = $q.defer(),
@@ -697,7 +743,7 @@ function $HttpProvider() {
// if we won't have the response in cache, send the request to the backend
if (!cachedResp) {
$httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout,
config.withCredentials);
config.withCredentials, config.responseType);
}
return promise;
@@ -752,10 +798,15 @@ function $HttpProvider() {
var parts = [];
forEachSorted(params, function(value, key) {
if (value == null || value == undefined) return;
if (isObject(value)) {
value = toJson(value);
}
parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));
if (!isArray(value)) value = [value];
forEach(value, function(v) {
if (isObject(v)) {
v = toJson(v);
}
parts.push(encodeURIComponent(key) + '=' +
encodeURIComponent(v));
});
});
return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&');
}
+7 -3
View File
@@ -32,7 +32,7 @@ function $HttpBackendProvider() {
function createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) {
// TODO(vojta): fix the signature
return function(method, url, post, callback, headers, timeout, withCredentials) {
return function(method, url, post, callback, headers, timeout, withCredentials, responseType) {
$browser.$$incOutstandingRequestCount();
url = url || $browser.url();
@@ -65,8 +65,8 @@ function createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument,
// always async
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
completeRequest(
callback, status || xhr.status, xhr.responseText, xhr.getAllResponseHeaders());
completeRequest(callback, status || xhr.status, xhr.response || xhr.responseText,
xhr.getAllResponseHeaders());
}
};
@@ -74,6 +74,10 @@ function createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument,
xhr.withCredentials = true;
}
if (responseType) {
xhr.responseType = responseType;
}
xhr.send(post || '');
if (timeout > 0) {
+16 -10
View File
@@ -52,7 +52,7 @@ function $InterpolateProvider() {
};
this.$get = ['$parse', function($parse) {
this.$get = ['$parse', '$exceptionHandler', function($parse, $exceptionHandler) {
var startSymbolLength = startSymbol.length,
endSymbolLength = endSymbol.length;
@@ -124,18 +124,24 @@ function $InterpolateProvider() {
if (!mustHaveExpression || hasInterpolation) {
concat.length = length;
fn = function(context) {
for(var i = 0, ii = length, part; i<ii; i++) {
if (typeof (part = parts[i]) == 'function') {
part = part(context);
if (part == null || part == undefined) {
part = '';
} else if (typeof part != 'string') {
part = toJson(part);
try {
for(var i = 0, ii = length, part; i<ii; i++) {
if (typeof (part = parts[i]) == 'function') {
part = part(context);
if (part == null || part == undefined) {
part = '';
} else if (typeof part != 'string') {
part = toJson(part);
}
}
concat[i] = part;
}
concat[i] = part;
return concat.join('');
}
catch(err) {
var newErr = new Error('Error while interpolating: ' + text + '\n' + err.toString());
$exceptionHandler(newErr);
}
return concat.join('');
};
fn.exp = text;
fn.parts = parts;
+45 -1
View File
@@ -33,7 +33,33 @@
</example>
*/
/**
* @ngdoc object
* @name ng.$logProvider
* @description
* Use the `$logProvider` to configure how the application logs messages
*/
function $LogProvider(){
var debug = true,
self = this;
/**
* @ngdoc property
* @name ng.$logProvider#debugEnabled
* @methodOf ng.$logProvider
* @description
* @param {string=} flag enable or disable debug level messages
* @returns {*} current value if used as getter or itself (chaining) if used as setter
*/
this.debugEnabled = function(flag) {
if (isDefined(flag)) {
debug = flag;
return this;
} else {
return debug;
}
};
this.$get = ['$window', function($window){
return {
/**
@@ -74,7 +100,25 @@ function $LogProvider(){
* @description
* Write an error message
*/
error: consoleLog('error')
error: consoleLog('error'),
/**
* @ngdoc method
* @name ng.$log#debug
* @methodOf ng.$log
*
* @description
* Write a debug message
*/
debug: (function () {
var fn = consoleLog('debug');
return function() {
if (debug) {
fn.apply(self, arguments);
}
}
}())
};
function formatError(arg) {

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