Compare commits

..

680 Commits

Author SHA1 Message Date
rodyhaddad 93b0c2d892 feat($parse): allow for assignments in ternary operator branches
Closes #8512
Closes #8484
CLoses #5434

Conflicts:
	test/ng/parseSpec.js
2014-08-11 17:04:40 +01:00
Peter Bacon Darwin d262378b7c fix(jqLite): allow triggerHandler() to accept custom event
In some scenarios you want to be able to specify properties on the event
that is passed to the event handler. JQuery does this by overloading the
first parameter (`eventName`). If it is an object with a `type` property
then we assume that it must be a custom event.

In this case the custom event must provide the `type` property which is
the name of the event to be triggered.  `triggerHandler` will continue to
provide dummy default functions for `preventDefault()`, `isDefaultPrevented()`
and `stopPropagation()` but you may override these with your own versions
in your custom object if you wish.

In addition the commit provides some performance and memory usage
improvements by only creating objects and doing work that is necessary.

This commit also renames the parameters inline with jQuery.

Closes #8469
Closes #8505
2014-08-11 12:17:55 +01:00
Peter Bacon Darwin 7729c84ec7 test(docsAppE2E): check that param defaults are shown in docs
Closes https://github.com/angular/dgeni-packages/pull/58
2014-08-10 20:19:23 +01:00
Peter Bacon Darwin dffeef29d7 test(docsAppE2E): tighten CSS selector to only find one element 2014-08-10 20:19:23 +01:00
Peter Bacon Darwin 2e22588ccf chore(package.json): update to dgeni-packages 0.9.7 2014-08-10 17:43:23 +01:00
Caitlin Potter 0b0acb0342 fix($compile): make '='-bindings NaN-aware
Update parent and child scopes correctly when a '='-binding changes from a NaN value.

TBR by angular-core

Closes #8553
Closes #8554

Conflicts:
	test/ng/compileSpec.js
2014-08-10 03:32:13 -04:00
Eddie Hedges 18fc43e828 docs(guide): correct links to unit testing guides
Closes #8548
2014-08-09 14:01:54 -04:00
Caitlin Potter ed47d811e2 chore(travis): specify chrome m34 in protractor configuration
Closes #8541
2014-08-08 17:21:00 -04:00
Derrick Mar a84f9f6178 docs(tutorial/step-10): add mock image data to spec
Closes #8468
Closes #8535
2014-08-08 20:37:42 +01:00
Caitlin Potter 4fbbe1152e docs(http): don't use locale-specific uri for MDN link 2014-08-08 15:32:38 -04:00
Joey Yang df3d941c57 docs($http): fix broken markdown link in withCredentials description
Markdown typo in $http config documentation

Closes #7859
2014-08-08 15:29:50 -04:00
Juampy 2bd3214a55 docs(guide/migration): ngSanitize is out ng core at AngularJS 1.2.21
When using ngBindHTML directive, either ngSanitize or $sce must be used
or this will end in a non-trusted value error.

Closes #8519
2014-08-07 21:04:17 -04:00
James Kleeh fc2abef327 docs(guide/directive): explain how to require multiple controllers
Closes #8524
2014-08-07 15:14:39 +01:00
Andrew Silluron 76a0eb89fb docs($compile): fix typo 'default' spelling
Change spelling of 'defualt' to 'default'

Closes #8476
2014-08-04 18:48:29 -04:00
Caitlin Potter ee57b4c26b docs(CHANGELOG.md): add missing breaking change from 1.3.0-beta.14 2014-08-04 17:29:33 -04:00
Peter Bacon Darwin 29eaabc000 test(select): relax test for IE8 bug
There is a bug in IE8 (http://support.microsoft.com/kb/829907 and
http://yuilibrary.com/forum-archive/forum/viewtopic.php@p=14826.html):
when you clone an `<option>` element the selected attribute on the options
can become invalid.

This is not relevant to the proper behaviour of the `select` directive
since it uses `prop` not `attr` to store the selected status of each
option.

This test is only interested in there being at least on option with
the `selected` attribute, for conformance to accessibility guidelines.
So we can safely relax the test to check this rather than concerning
ourselves with which option actually has this attribute.

Fixes 79538afd7b
Closes #8465
2014-08-03 22:15:59 +01:00
Joseph Spencer 2a6081057f docs($resource): clarify the meaning of @ in paramDefaults
Closes #8457
2014-08-03 17:15:03 +01:00
Peter Bacon Darwin 79538afd7b fix(select): ensure that at least one option has the selected attribute set
Using `prop` to set selected is correct programmatically but accessibility
guidelines suggest that at least on item should have the `selected` attribute
set.

Closes #8366
Closes #8429

Conflicts:
	test/ng/directive/selectSpec.js
2014-08-03 16:37:32 +01:00
rodyhaddad bcfa64e77c chore(travis): rename fetch_bundle script and make it not abort a travis build if it fails
This is useful when the npm-bundle-deps server isn't running,
when the tar never gets served (there's a default timeout on the request),
or when the served file isn't a valid tar.
2014-08-01 19:14:48 -07:00
Peter Bacon Darwin b7a2deed30 docs(ngSubmit): add link to form docs to discourage double submission
Closes #6017
2014-07-31 21:27:04 +01:00
Ken Sheedlo 98ff901bda docs(error/$injector/unpr): inadvertently redefining a module can cause error
Closes #8421
2014-07-31 20:48:32 +01:00
k-funk 428b81cba9 docs($http): add link to $http.path()
Closes #8424
2014-07-31 13:43:48 +01:00
Danielle 5dae9c230e docs(ngMockE2E): remove repeated word
Closes #8411
2014-07-31 13:41:05 +01:00
winsontam c3fad1157e fix($location) don't rewrite location when clicking on "javascript:" or "mailto:" link
Previously, absent a specified target attribute, when clicking on an anchor tag with an href beginning
with either "javascript:" or "mailto:", the framework would rewrite the URL, when it ought not to.

With this change, the browser is prevented from rewriting if the URL begins with a case-insensitive match
for "javascript:" or "mailto:", optionally preceeded by whitespace.

Closes #8407
Closes #8425
Closes #8426
2014-07-31 07:31:33 -04:00
Peter Bacon Darwin 9242c580a1 refact(select): don't recreate selectedSet on every digest loop
In the case of a "multiple" select, the model value is an array, changes
to which don't get picked up by NgModelController as it only looks for
object identity change.

We were rebuilding the `selectedSet` (a hash map of selected items) from
the modelValue on every turn of the digest. This is not needed as we can
simply use `$watchCollection` directly on the `$modelValue` instead.
2014-07-31 07:14:14 +01:00
Peter Bacon Darwin c2860944c6 fix(select): do not update selected property of an option element on digest with no change event
The `render()` method was being invoked on every turn of the digest cycle,
which was inadvertently updating the DOM even when a `change` event had
not been triggered.

This change only calls the `render()` method when `ctrl.$render()` is called,
as part of the NgModelController` lifecycle and when the `modelValue` has
significantly changed.

Closes #8221
Closes #7715
2014-07-30 23:14:40 +01:00
Peter Bacon Darwin e9a00fbdc3 test(select): add extra expectations and comments for clarity 2014-07-30 23:14:40 +01:00
Erin Altenhof-Long d018ac2a9a test(select): add test of updating the model because of ng-change
A regression #7855 was introduced by
https://github.com/angular/angular.js/commit/dc149de9364c66b988f169f67cad39577ba43434
This test ensures that reverting that commit fixes this regression.
In the regression, changes to a bound model in ng-change were not propagated back to the view.

Test for #7855
2014-07-30 23:14:40 +01:00
Erin Altenhof-Long b770c353bc test(select): add test cases for selects with blank disabled options
An earlier commit dc149de936 caused an error where the first option of
a select would be skipped over if it had a blank disabled value. These tests demonstrate that with
that commit in place, blank disabled options are skipped in a select. When the commit is reverted,
the correct behavior is seen that the blank disabled option is still selected in both selects
marked with required and those that have optional choices.

Relates to #7715
2014-07-30 23:14:40 +01:00
Erin Altenhof-Long 812277c257 test(select): add test against updating selected property on digest with no change event
Commit dc149de936 was reverted to fix regressions #7715 and #7855.
This commit introduced this test case and a corresponding fix for preventing the update of the
selected property of an option element on a digest with no change event. Although the previous fix
introduced regressions, the test covers a valid issue and should be included.
2014-07-30 23:14:39 +01:00
Erin Altenhof-Long 61871da9de revert(select): avoid checking option element selected properties in render
This reverts commit dc149de936. That commit fixes a bug caused by
Firefox updating `select.value` on hover. However, it
causes other bugs with select including the issue described in #7715. This issue details how
selects with a blank disabled option skip to the second option. We filed a bug
with Firefox for the problematic behavior the reverted commit addresses
https://bugzilla.mozilla.org/show_bug.cgi?id=1039047, and alternate Angular fixes are being
investigated.

Closes #7715 #7855
2014-07-30 23:14:39 +01:00
Caitlin Potter 9ee075518f fix(ngSanitize): ensure html is a string in htmlParser()
Previously, $sanitize(nonString) would throw. Now, the type is converted to a string before any work
is done.

Closes #8417
Closes #8416
2014-07-30 13:34:14 -04:00
Misha Moroshko afe93eaff8 docs(dateFilter): fix milliseconds example
Closes #8389
2014-07-29 17:49:28 +01:00
Andrew Pham d8f94d1a3f docs(tutorial/step-2): warn reader not to minimise browser that Karma's running on
Closes #8386
2014-07-29 17:40:46 +01:00
Nathan Wiebe f53b53df22 docs(tutorial): clarify sentence in step 02
Separate two sentences with a period, and clarify the wording by making it less technical: "to the DOM"
vs "to the <body> tag".

Closes #8394
2014-07-29 11:42:15 -04:00
Shahar Talmi eab5731afc feat(http): allow caching for JSONP requests
Closes #1947
Closes #8356
2014-07-29 09:40:36 +01:00
Sergio Sanguanini 986c446aaf style(AngularPublic): add whitespace to jshint block
Closes #8360
2014-07-27 14:10:40 +01:00
rodyhaddad 60366c8d0b fix($parse): correctly assign expressions who's path is undefined and that use brackets notation
Closes #8039
2014-07-26 23:28:20 -07:00
Julie Ralph 494c8aa0b3 chore(ci): update sauce connect from 3 to 4.3 for the 1.2.x branch 2014-07-25 14:50:24 -07:00
Ivan Alvarez cd9459e129 docs(tutorial): update step_03.ngdoc
1) The original document is not clear to a new developer in where to place the code.
2) The query.clear() statement to clear the query before the second test is missing in the original document.
3) Refactored to use the query and phoneList variables in both tests, so its easier to read and understand.

Closes #7815
2014-07-25 14:26:49 -07:00
Mitch Robb 2862883bd8 docs(tutorial): update step7 ngdoc to fix grammar
This line was missing an 'as'

Previous:
We also have to add the modules dependencies of our app. By listing these two modules as dependencies of `phonecatApp`, ...

New:
We also have to add the modules *as* dependencies of our app.

Closes #8345
2014-07-25 14:12:59 -07:00
Jeff Cross bbb673a48a docs(changelog): release notes for 1.3.0-beta.17 and 1.2.21 2014-07-25 10:17:16 -07:00
Jeff Cross cd9afd9961 revert: fix(ngHref): remove attribute when empty value instead of ignoring
This reverts commit 948c86c602.

This commit caused tests to fail in IE8 due to a TypeError '0.childNodes is
null or not an object. The issue should be investigated and fixed. Issue #8340
has been opened to investigate.

See this job for failures: https://travis-ci.org/angular/angular.js/jobs/30792508
2014-07-25 09:01:43 -07:00
Shahar Talmi e25ed0d48d fix(angular.copy): clone regexp flags correctly
Closes #5781
Closes #8337
2014-07-25 16:40:14 +01:00
Peter Bacon Darwin cd6d21e78a docs(tutorial/step-2): note that ng-app now needs a module name
Closes #7655
2014-07-25 16:38:55 +01:00
TheMrSteve 9cf5b35e5c docs(tutorial/step-3): note that the server needs to be running before running Protractor
Closes #7142
2014-07-25 16:38:55 +01:00
Jeff Cross 5d11e02008 fix(docs): change plnkr form to open in same window
Form previously posted to target="_blank", but pop-up blockers were causing this to not work.
If a user chose to bypass pop-up blocker one time and click the link, they would arrive at
a new default plnkr, not a plnkr with the desired template.

This fix removes the _blank target, causing the plnkr to open in the current window/tab.
2014-07-24 14:37:49 -07:00
Chris Chua 209e600070 fix(jqLite): triggerHandler support unbind self
Fixes .one if the event is invoked from triggerHandler.

Closes #5984

Conflicts:
	test/jqLiteSpec.js
2014-07-24 13:50:28 -07:00
Igor Minar ceaca57786 revert: perf($parse): don't use reflective calls in generated functions
This reverts commit cbdf0c2afb.

The commit causes tests failures on IE8. I'm not quite sure why and I can't
investigate now.

Failed build: https://travis-ci.org/angular/angular.js/jobs/30756773
2014-07-24 09:07:57 -07:00
Igor Minar cbdf0c2afb perf($parse): don't use reflective calls in generated functions
Chrome and FF are smart enough to notice that the key is is a string literal, so this change doesn't
make a difference there. Safari gets a boost. I haven't tested IE, but it can't cause harm there. :)

http://jsperf.com/fn-dereferencing
2014-07-24 07:43:00 -07:00
Patrick Hallisey 1111076552 docs($resource): note methods list is non-exhaustive
The existing documentation for custom action methods implies that only a small
list of upper case methods can be used for custom $resource actions.
2014-07-23 15:02:44 -07:00
Shahar Talmi 948c86c602 fix(ngHref): remove attribute when empty value instead of ignoring
Closes #2755
2014-07-23 13:42:27 -07:00
Diego Plentz cd63ff497d docs(guide/concepts): update example
The "A first example: Data binding" section it implies that the `required` directive is
doing something, but it isn't.

I just removed the parts the refer to the required directive to avoid confusion.
2014-07-23 11:34:32 -07:00
Karl Yang 9d6240561b docs(tutorial): remove index.html from app url 2014-07-23 10:32:58 -07:00
Chad Smith 05b5245790 docs(guide): remove redundancy in providers guide
Highlighted the Best Practices section, and took the styling from the Services doc.
Also removed some superfluous wording that was in the "Provider Recipe"
2014-07-23 09:21:36 -07:00
Shahar Talmi e6ebfc87c9 refactor(Angular): add isPromiseLike helper function
This can be used internally to remove the repeating pattern of `obj && obj.then`. For now, I don't see a good reason to expose this in angular's public interface.

Conflicts:
	src/Angular.js
2014-07-22 16:35:02 -07:00
Julie Ralph 7f2bcc3933 chore(e2e): protractor version bump to 1.0 2014-07-22 15:29:00 -07:00
Igor Minar 492b0cdf28 perf(forEach): use native for loop instead of forEach for Arrays
Conflicts:
	src/Angular.js
2014-07-22 11:40:59 -07:00
hanstest 51863f80d7 docs(guide/directive): fix formatting 2014-07-22 10:34:08 -07:00
Peter Bacon Darwin 9d4000d689 docs(guide/$location): fix up example protractor tests
Closes #8255
2014-07-22 17:55:48 +01:00
vdyckn bc036c68ac docs(guide/$location) global cntl deprecated
Closes #8255
2014-07-22 17:55:48 +01:00
Shane Keller 580135a9cb docs(guide/scope): add missing period 2014-07-21 17:21:34 -07:00
Jason Hamm da0c5efa72 docs(guide/bootstrap): fix example 2014-07-21 16:53:43 -07:00
Vikram Soni c280d5ab02 Updated e2e spec to remove warning
on
element(by.css(.phones li a)).click();

selenium will throw a warning message that more then one element found.

element.all(by.css('.phones li a')).first().click(); fixes the issue
2014-07-21 16:10:42 -07:00
Jesse Palmer 28c8199cd6 docs(misc/faq): minor formatting fixes 2014-07-21 15:30:13 -07:00
garetht 0252a9889b docs($http) Clarify how to specify JSONP callback.
Make clear that it is the name of the callback that should be `JSON_CALLBACK`, instead of the current vague description.

Closes #8269
2014-07-21 14:55:15 -07:00
Trey Hunner 1c15cdc2d0 style: fix whitespace issues
Closes #8277

Conflicts:
	docs/content/guide/migration.ngdoc
2014-07-21 14:52:06 -07:00
Nick Van Dyck 0bd329d4fd docs(guide/concepts): use protocol relative URL
When accessing the docs from https, the "Accessing the backend example fails
because it contains a hard coded protocol. By making the URL protocol relative,
the example should work over http and https.
2014-07-21 14:45:16 -07:00
Trey Hunner 8db84a16db chore(.editorconfig): add .editorconfig file
Closes #8278
2014-07-21 14:43:59 -07:00
Igor Minar cffcfc73a0 style($http): fix indentation 2014-07-21 14:43:48 -07:00
Peter Bacon Darwin 25eb9b794f docs(ngMock) add @packageName tag to fix invalid module overview pages
Closes #7284
Closes #8038
2014-07-21 21:03:40 +01:00
Peter Bacon Darwin 6941779543 chore(package): update dgeni-package to v0.9.6
This version supports `@packageName` tag that will allow us to fix the docs
for ngMock and ngMockE2E
2014-07-21 21:03:40 +01:00
xi 65f40d2123 docs(ngBind): fix wording
You can not change the use of `{{}}`/`ngBind` based on the time when it is used.
So this should be "if".

Closes #7786
2014-07-18 15:54:57 -07:00
rodyhaddad e159f9626c chore(travis): get npm dependencies from npm-bundle-deps
npm-bundle-deps has been rewritten to be more robust
2014-07-18 15:37:20 -07:00
Peter Bacon Darwin 685a9d040d docs(indexPage): move latest versions to the top
Closes #7513
2014-07-18 22:04:08 +01:00
Igor Minar 8eede099cd perf(ngBindHtml): move addClass to the compile phase
Closes #8261

Conflicts:
	src/ng/directive/ngBind.js
2014-07-18 13:52:06 -07:00
Brian Ford a17d42d706 docs(changelog): release notes for 1.3.0-beta.16 pizza-transubstantiation 2014-07-18 12:21:28 -07:00
Carlo s A. Guillen 60af504c18 fix($location): handle plus character in query strings
Closes #3042
2014-07-18 08:37:59 -07:00
Peter Bacon Darwin 243d9ac72c docs(guide/module): add protractor tests 2014-07-18 11:12:49 +01:00
Peter Bacon Darwin cc8eb91665 style(guide/module): use dot first style when chaining 2014-07-18 11:12:49 +01:00
Nick Van Dyck 8697c3bf4c docs(guide/module) fixed global controller in example
Global controllers have been disallowed in Angular 1.3

Closes #8248
2014-07-18 11:12:49 +01:00
Jason Bedard 3c46c94342 perf(jqLite): expose the low-level jqLite.data/removeData calls
- updated the internal jqLite helpers to use the low-level jqLite.data/removeData to avoid unnecessary jq wrappers and loops
- updated $compile to use the low-level jqLite.data/removeData to avoid unnecessary jq wrappers at link time
2014-07-17 17:18:35 -07:00
Jason Bedard 71eb1901f6 perf($compile): only create jqLite object when necessary 2014-07-17 17:15:21 -07:00
Brian Ford 4e57e28589 docs(triaging): clarify severity and frequency labels 2014-07-17 12:32:23 -07:00
Peter Bacon Darwin 13289c0903 chore(package): update to latest dgeni-packages
This fixes an issue with HTML encoding HTML entities in code blocks
2014-07-17 13:05:00 +01:00
Julie Ralph afdb4f1b76 chore(ci): update protractor to 1.0.0-rc5 and increase global timeout for loading pages
This should help with occasional safari page load timeouts. In a test of
4500 page loads, the current 10 second limit caused 3 errors while a 30 second limit
caused none.

Closes #8231
2014-07-16 23:10:05 -07:00
Josh Schreuder e7999e7447 docs($interval): fix missing square brackets in example
Closes #8228
2014-07-16 20:42:43 -04:00
Caitlin Potter d175bb0131 fix(ngSanitize): follow HTML parser rules for start tags / allow < in text content
ngSanitize will now permit opening braces in text content, provided they are not followed by either
an unescaped backslash, or by an ASCII letter (u+0041 - u+005A, u+0061 - u+007A), in compliance with
rules of the parsing spec, without taking insertion mode into account.

BREAKING CHANGE

Previously, $sanitize would "fix" invalid markup in which a space preceded alphanumeric characters
in a start-tag. Following this change, any opening angle bracket which is not followed by either a
forward slash, or by an ASCII letter (a-z | A-Z) will not be considered a start tag delimiter, per
the HTML parsing spec (http://www.whatwg.org/specs/web-apps/current-work/multipage/parsing.html).

Closes #8212
Closes #8193
2014-07-16 19:56:39 -04:00
Michał Gołębiowski fe1188daf3 refactor(jshint): reduce duplication & test all JS files
Conflicts:
	src/Angular.js
	src/AngularPublic.js
	src/jqLite.js
	src/ng/directive/input.js
2014-07-16 19:56:14 -04:00
Michał Gołębiowski e1a3a6251f chore(jshint): update grunt-contrib-jshint 2014-07-16 19:19:21 -04:00
Caitlin Potter 25d3d3730d revert: fix(ngSanitize): follow HTML parser rules for start tags / allow < in text content
This reverts commit 36d2658b94.

This commit broke the ci-checks task when ported into v1.2.x --- I will sort this out shortly.
2014-07-16 18:13:17 -04:00
Caitlin Potter af5aacce05 test(jqLite): make iframe contents() test less flaky 2014-07-16 17:47:57 -04:00
Paul Harris 3abd0fb93c test(filter): fix typo in descriptions
Two descriptions contain typo's to the word predicate.

Closes #8004
2014-07-16 17:05:01 -04:00
Caitlin Potter 36d2658b94 fix(ngSanitize): follow HTML parser rules for start tags / allow < in text content
ngSanitize will now permit opening braces in text content, provided they are not followed by either
an unescaped backslash, or by an ASCII letter (u+0041 - u+005A, u+0061 - u+007A), in compliance with
rules of the parsing spec, without taking insertion mode into account.

BREAKING CHANGE

Previously, $sanitize would "fix" invalid markup in which a space preceded alphanumeric characters
in a start-tag. Following this change, any opening angle bracket which is not followed by either a
forward slash, or by an ASCII letter (a-z | A-Z) will not be considered a start tag delimiter, per
the HTML parsing spec (http://www.whatwg.org/specs/web-apps/current-work/multipage/parsing.html).

Closes #8212
Closes #8193
2014-07-16 16:59:04 -04:00
Izhaki 6ce5a04d42 docs($compile): fix template and replace properties' docs
Closes #8062
2014-07-16 13:43:05 -07:00
Caitlin Potter 929064d9e4 test($http): ignore date-toJSON test if running in IE8
IE8 does not implement Date.prototype.toISOString(), which is necessary for this feature. The
feature still works if this method is polyfilled, but these tests are not run with polyfills.
2014-07-16 12:06:48 -04:00
Caitlin Potter d0b873a4b7 revert: chore(travis): get npm dependencies from npm-bundle-deps
This commit was causing some issues with CI testing, so it's being temporarily removed until that's
resolved.

This reverts commit 8881606cd9.
2014-07-16 11:34:43 -04:00
Almar 2e10659472 docs(misc core): fixed broken angular.copy example
The module was not being registered, and this broke the example for who knows how long!

Closes #8218
2014-07-16 11:30:38 -04:00
Max 2a8493f40c docs(guide/forms): fix controller name in example
The "Binding to form and control state" sample had the wrong controller name

Closes #8206
2014-07-16 11:16:38 +01:00
Dan Barua 2f960f1530 fix($http): fix double-quoted date issue when encoding params
This commit special cases date handling rather than calling toJSON as we always need
a string representation of the object.

$http was wrapping dates in double quotes leading to query strings like this:
  ?date=%222014-07-07T23:00:00.000Z%22

Closes #8150
Closes #6128
Closes #8154
2014-07-15 17:18:38 -07:00
rodyhaddad 3f5f20fe77 chore(travis): get npm dependencies from npm-bundle-deps 2014-07-15 17:09:51 -07:00
Christian 01387c0a8f docs(orderBy filter): fix controller name in example
Closes #8133
Closes #8206
2014-07-15 17:57:03 +01:00
rodyhaddad c0afbfaca5 fix(select): force visual update in IE
IE9, IE10 and IE11 would always show the first <option> as
selected when the user moves from a null <option>
to a non-null one in a non-null <select>.
Even though the model was being updated correctly,
visually, the first <option> always appeared selected.

Setting the `selected` property twice in a row
seems to fix it in all the three versions mentioned above.

Closes #7692
Closes #8158
2014-07-15 09:47:22 -07:00
Shahar Talmi bf13d2683d fix($rootScope): $watchCollection should handle NaN in objects
This fixes a potential infinite digest in $watchCollection when one of the values is NaN. This was previously fixed for arrays, but needs to be handled for objects as well.

Closes #7930
2014-07-15 09:45:13 -07:00
Peter Bacon Darwin fe01a85a8e style(orderBySpec): fix indentation 2014-07-15 14:29:25 +01:00
Peter Bacon Darwin 6b9a332959 style($route): convert tab indent to spaces 2014-07-15 14:01:09 +01:00
Sekib Omazic f1b28847c8 fix(orderBy): correctly order by date values
Closes #6675
Closes #6746
2014-07-15 13:41:27 +01:00
Jason Miller 1b779028fd fix(ngRoute): remove unnecessary call to decodeURIComponent
Since `$location.$$path` is already decoded, doing an extra `decodeURIComponent` is both unnecessary
and can cause problems. Specifically, if the path originally includes an encoded `%` (aka `%25`),
then ngRoute will throw "URIError: URI malformed".

Closes #6326
Closes #6327
2014-07-15 13:24:40 +01:00
Wladimir Coka 49b2a1c8cf refactor($parse): improve readability on conditional assignment
Use logical OR operator instead of if statement

Closes #5065
2014-07-15 12:49:00 +01:00
Wladimir Coka 3e82492fc6 refactor($http): improve readability on conditional assignment
Use ternary operator instead of if statement

Closes #5065
2014-07-15 12:48:48 +01:00
Wladimir Coka 856be44628 refactor(dateFilter): improve readability on conditional assignment
Use ternary operator instead of if statement

Closes #5065
2014-07-15 12:48:39 +01:00
Wladimir Coka dbb21b1531 refactor($compile): improve readability on conditional assignment
Use ternary operator instead of if statement

Closes #5065
2014-07-15 12:48:09 +01:00
Peter Bacon Darwin 3ce56b739c docs(guide/unit-testing): add info on testing element transclude directives
Closes #4505
Closes #8197
2014-07-15 12:40:26 +01:00
Bill Neubauer ecbb374826 docs(tutorial/step-9): link to list of filters rather than filterProvider
Closes #8082
2014-07-15 12:40:26 +01:00
Igor Minar 0e5d31908e fix(csp): fix autodetection of CSP + better docs
CSP spec got changed and it is no longer possible to autodetect if a policy is
active without triggering a CSP error:

https://github.com/w3c/webappsec/commit/18882953ce2d8afca25f685557fef0e0471b2c9a

Now we use `new Function('')` to detect if CSP is on. To prevent error from this
detection to show up in console developers have to use the ngCsp directive.

(This problem became more severe after our recent removal of `simpleGetterFn`
 which made us depend on function constructor for all expressions.)

Closes #8162
Closes #8191
2014-07-14 17:20:06 -07:00
standup75 f1b0d21f97 docs(ngAnimate): ensure the CSS breakdown example uses a compound selector 2014-07-14 11:29:35 -04:00
Igor Minar 58e94dcde9 docs($parse:isecdom): add a section about return values and CoffeeScript
Closes #7973
2014-07-12 20:24:20 -07:00
Erin Altenhof-Long eba192b863 docs(CHANGELOG): add v1.3.0-beta.15 and v1.2.20 changes 2014-07-11 11:26:39 -07:00
rodyhaddad 75099e6137 chore($parse): remove simpleGetter optimizations as they're no longer valid
Closes #8101
2014-07-10 15:17:41 -07:00
perek 172a40931b fix($http) - add ability to remove default headers
Fixes #5784
Closes #5785
2014-07-10 14:38:19 -07:00
Igor Minar 23e5109b64 chore(travis): disable our npm registry cache 2014-07-09 06:43:05 -07:00
Michał Gołębiowski cc84ce3bf5 chore(travis): disable npm spinner & enable HTTP logs; run npm install twice
It's good to have HTTP logs on Travis for debugging purposes and the spinner
doesn't integrate with Travis very well & messes the output.
2014-07-09 12:42:57 +02:00
Michał Gołębiowski bee2d1fbb9 chore(travis): declare Node.js version as '0.10', not 0.10 (which is 0.1) 2014-07-09 11:45:17 +02:00
fuqcool 7101a02c93 docs(error/$sce/insecurl): fix links to $sce and $sceDelegateProvider 2014-07-08 22:40:06 -07:00
Julie Ralph 888be00712 chore(tests): fix warning about a non-unique element locator in e2e tests 2014-07-08 16:28:12 -07:00
Julie Ralph 05597c24c7 chore(e2e): update protractor to 1.0.0-rc4
This change contains a stability improvement to use data URLs instead of
about:blank for resetting the URL.
2014-07-08 16:22:52 -07:00
Domenico Matteo bf55f23325 docs(guide/i18n): fix typo 2014-07-08 03:35:04 -07:00
Brian Ford ab051e78ea docs(select): update example to use a module 2014-07-08 02:32:21 -07:00
Brian Ford 87d46a84c3 docs(guide/expression): update examples to use modules 2014-07-08 02:32:21 -07:00
Brian Ford ae764f1844 docs(linky): update example to use a module 2014-07-08 02:32:21 -07:00
Brian Ford ad8092ed80 docs(angular.copy): update example to use a module 2014-07-08 02:32:21 -07:00
Brian Ford 55e1b3e1c8 docs($sanitize): update example to use a module 2014-07-08 02:32:20 -07:00
Brian Ford 6f465a2b26 docs(guide/scope): update examples to use modules 2014-07-08 02:32:20 -07:00
Brian Ford 3ecac62251 docs(guide/forms): update examples to use modules 2014-07-08 02:32:20 -07:00
Brian Ford c64610269d docs($location): update example to use a module 2014-07-08 02:32:20 -07:00
Brian Ford 5c2302949b docs($cookies): update examples to use modules 2014-07-08 02:32:20 -07:00
Brian Ford 7c84e2632f docs(orderBy): update examples to use modules 2014-07-08 02:32:20 -07:00
Brian Ford 18d18f07db docs(limitTo): update example to use a module 2014-07-08 02:32:20 -07:00
Brian Ford 9f5be534fc docs(ngTransclude): update example to use a module 2014-07-08 02:32:20 -07:00
Brian Ford 1cd7912614 docs($log): update example to use a module 2014-07-08 02:32:19 -07:00
Brian Ford 514da451fc docs(ngPluralize): update example to use a module 2014-07-08 02:32:19 -07:00
Brian Ford 2788cc4e12 docs(ngSwitch): update example to use a module 2014-07-08 02:32:19 -07:00
Brian Ford 7f6322df6a docs(ngInit): update example to use a module 2014-07-08 02:32:19 -07:00
Brian Ford 5bd8613168 docs(ngValue): update example to use a module 2014-07-08 02:32:19 -07:00
Brian Ford 32b507890e docs(ngList): update example to use a module 2014-07-08 02:32:19 -07:00
Brian Ford bfedafdede docs(ngInclude): update example to use a module 2014-07-08 02:32:19 -07:00
Brian Ford cdefbe3425 docs($interval): update example to use a module 2014-07-08 02:32:19 -07:00
Brian Ford f75f4bce82 docs(filters): update examples to use modules 2014-07-08 02:32:19 -07:00
Brian Ford 4349de3d41 docs(ngController): update examples to use modules 2014-07-08 02:32:18 -07:00
Brian Ford df545d7eed docs($window): update example to use a module 2014-07-08 02:32:18 -07:00
Brian Ford 3b5f346314 docs(ngSubmit): update example to use a module 2014-07-08 02:32:18 -07:00
Brian Ford 3aab87b381 docs(ngBind): update examples to use modules 2014-07-08 02:32:18 -07:00
Brian Ford 0973175058 docs($http): update example to use a module 2014-07-08 02:32:18 -07:00
Brian Ford 112da45c07 docs($document): update example to use a module 2014-07-08 02:32:18 -07:00
Brian Ford e3dc85841d docs(ngChange): update example to use a module 2014-07-08 02:32:18 -07:00
Brian Ford ef1c352bc9 docs(ngModel): update examples to use modules 2014-07-08 02:32:18 -07:00
Brian Ford a5b6444324 docs(formDirective): update example to use a module 2014-07-08 02:32:17 -07:00
Brian Ford dd18c00b1d docs($compile): update example to use a module 2014-07-08 02:32:17 -07:00
Shahar Talmi a0fad24dc2 chore(jshint): enforce jshint for tests
Closes #8023
Closes #8026
2014-07-08 00:34:50 -07:00
Shahar Talmi da0e3c99f5 fix(input): escape forward slash in email regexp
This messed up with syntax coloring and variable hovering in chrome developer tools and made debugging really difficult.

Closes #8096
2014-07-07 16:26:27 -04:00
Julie Ralph a41c58e285 chore(tests): increase timeout for navigation in ng-href tests to avoid timeouts
Previously, the timeout for ng-href tests waiting for the url change after a link
was clicked was only 1000 ms. This was causing some flaky timeouts, so increasing
the wait to 5000 ms.
2014-07-07 11:21:33 -07:00
Julie Ralph bce5b49133 chore(e2e): update protractor to 1.0.0-rc2 and add more logging
Use the new options from the reporter to add more logging to end to end tests,
and increase the Jasmine test timeout from 30 seconds to 60 seconds to allow for
legitimately long-lasting tests.
2014-07-07 11:07:48 -07:00
Kevin Brogan 816b84230c fix(input): modify email validation regexp to match rfc1035
Previously, domain parts which began with or ended with a dash, would be accepted as valid. This CL matches Angular's email validation with that of Chromium and Firefox.

Closes #6026
2014-07-07 13:51:58 -04:00
Caitlin Potter 873acf8fab fix(parseKeyValue): ignore properties in prototype chain.
Previously, properties (typically functions) in the prototype chain (Object.prototype) would shadow
query parameters, and cause them to be serialized incorrectly.

This CL guards against this by using hasOwnProperty() to ensure that only own properties are a concern.

Closes #8070
Fixes #8068
2014-07-03 21:58:10 -04:00
Matias Niemelä 9063a0c2e7 chore(ngAnimate): fix broken IE8 tests for ngAnimateChildren 2014-07-04 02:14:57 +03:00
Chris Kuehl 03cbc0d6b1 docs(error/$rootScope/inprog): fix $timeout typo
Closes #8071
2014-07-03 17:33:02 -04:00
Matias Niemelä 931789ec14 feat(ngAnimate): conditionally allow child animations to run in parallel with parent animations
By default ngAnimate prevents child animations from running when a parent is performing an animation.
However there are a cases when an application should allow all child animations to run without blocking
each other. By placing the `ng-animate-children` flag in the template, this effect can now be put to
use within the template.

Closes #7946
2014-07-03 19:35:17 +03:00
Peter Bacon Darwin 9bc807783f docs($httpProvider): revert removal of comments
Related to #7782
2014-07-03 13:29:24 +01:00
Cory Boyd 2d6ee651b1 docs($httpProvider): add missing documentation
Add documentation for $httpProvider default values

Closes #6682
2014-07-03 13:24:48 +01:00
Peter Bacon Darwin 7ca24a8264 chore(docs/css): add margin between ul and p elements
Bootstrap CSS was removing the margin after ul elements if they were
descendents of other ul elements. But if the ul was followed by a p
then this looked terrible.

Related to #5953
2014-07-03 12:51:21 +01:00
Peter Bacon Darwin 1d8e42070a docs(tutorial/step-0): remove hyphen and clarify items
Closes #5953
2014-07-03 12:51:21 +01:00
Robert Kielty fe6b2fbfc4 docs(tutorial/step-7): improve injector information
I attempted to tighten up the language around the DI overview so that it was clearer
and more explicit. The sole responsibilities sentence was semantically jarring and
I think looks better as a list.  Some minor grammar improvements.

Closes #7099
2014-07-03 12:24:15 +01:00
Peter Bacon Darwin 5a222244fb docs(guide/controller): tweak initial example 2014-07-03 12:13:49 +01:00
cranesandcaff 4026074aba docs(guide/controller): only show best practice controller creation
If it is not recommended to use a global function to create controllers,
why should it be shown as possible in the documentation?

One of the most common complaints about AngularJS is that it doesn't enforce
any convention. This is intentional and I generally like this.
However if we can avoid outright bad implementations in examples I believe
we should.

Closes #8011
2014-07-03 12:13:49 +01:00
Peter Bacon Darwin d9a596addd docs(guide/di): further clarification of what can be injected 2014-07-03 10:13:58 +01:00
Artiom Neganov 8c0898b21c docs(guide/di): clarify what "services" can be injected into .config() and .run()
Closes #8106
2014-07-03 10:13:58 +01:00
Mike Haas d9b693bb7a docs($compile): fix minor typo
Closes #8048
2014-07-03 09:51:40 +01:00
Peter Bacon Darwin da94ab2e63 docs($logProvider): debugEnabled is a method not a property
Closes #7824
2014-07-03 09:51:40 +01:00
Peter Bacon Darwin 2fd8dc7061 docs($sce): fix code samples and example
The code samples were using `<pre>` tags rather than code fences (```) so they were
not being displayed correctly.

The inline code example (defined by a `<example>` element) had been placed in an
`@example` jsdoc tag, so rather than appearing inline at the declaration point in
the text, they were being appended to the end of the document in the `Example` section.

Closes #8053
2014-07-03 07:05:32 +01:00
Caitlin Potter 01012a4d7a chore(watchr-docs): remove watchr-docs.rb
This file hasn't changed in forever, and doesn't seem to be in use any longer.

Closes #7978
2014-07-02 17:59:58 -04:00
jpsimons ce84429adf docs($location): update $location.search() jsdoc signature
Closes #8050
2014-07-02 13:55:24 -07:00
Sekib Omazic a26acb64fe fix($location): remove query args when passed in object
Query args will be removed from $location search object if they are passed in as null or undefined object properties

Closes #6565
2014-07-01 08:41:15 -07:00
Igor Minar 7088ed1ed3 docs($parse): add missing 'isecobj' error page 2014-07-01 06:36:50 -07:00
Martin Staffa 7027844d42 fix($http): don't remove content-type header if data is set by request transform
Fixes #7910
2014-06-30 16:58:15 -07:00
Carlo s A. Guillen 16c584ed7f docs(CHANGELOG.md): add changes for 1.3.0-beta.14 and 1.2.19 2014-06-30 16:58:15 -07:00
Michał Gołębiowski b586bfdfab fix(testabilityPatch): fix invocations of angular.mock.dump 2014-06-30 16:58:15 -07:00
Igor Minar 1d69015e3d test($parse): skip Function.prototype.bind test on IE8 2014-06-30 11:22:41 -07:00
Igor Minar f13c33bf10 fix($parse): don't check Function.prototype.bind when it doesn't exist
e.g. IE8 doesn't have it
2014-06-30 11:15:39 -07:00
Igor Minar ba62e975f1 fix($parse): make the window check in ensureSafeObject IE8 friendly 2014-06-30 11:06:18 -07:00
rodyhaddad b89d941cdf style(parseSpec): make jshint happy 2014-06-30 10:50:02 -07:00
rodyhaddad 07fa87a8a8 fix($parse): prevent invocation of Function's bind, call and apply
BREAKING CHANGE:
You can no longer invoke .bind, .call or .apply on a function in angular expressions.
This is to disallow changing the behaviour of existing functions
in an unforseen fashion.
2014-06-30 10:43:29 -07:00
rodyhaddad 0af70eb99e refactor($parse): move around previous security changes made to $parse 2014-06-30 10:40:24 -07:00
Jann Horn cb713e6045 fix($parse): forbid __proto__ properties in angular expressions
__proto__ can be used to mess with global prototypes and it's
deprecated. Therefore, blacklisting it seems like a good idea.

BREAKING CHANGE:
The (deprecated) __proto__ propery does not work inside angular expressions
anymore.
2014-06-30 09:32:38 -07:00
Jann Horn 89ca859734 fix($parse): forbid __{define,lookup}{Getter,Setter}__ properties
It was possible to use `{}.__defineGetter__.call(null, 'alert', (0).valueOf.bind(0))` to set
`window.alert` to a false-ish value, thereby breaking the `isWindow` check, which might lead
to arbitrary code execution in browsers that let you obtain the window object using Array methods.
Prevent that by blacklisting the nasty __{define,lookup}{Getter,Setter}__ properties.

BREAKING CHANGE:
This prevents the use of __{define,lookup}{Getter,Setter}__ inside angular
expressions. If you really need them for some reason, please wrap/bind them to make them
less dangerous, then make them available through the scope object.
2014-06-30 09:29:53 -07:00
Jann Horn bc6fb7cc94 fix($parse): forbid referencing Object in angular expressions
It was possible to run arbitrary JS from inside angular expressions using the
`Object.getOwnPropertyDescriptor` method like this since commit 4ab16aaa:
    ''.sub.call.call(
      ({})["constructor"].getOwnPropertyDescriptor(''.sub.__proto__, "constructor").value,
      null,
      "alert(1)"
    )()
Fix that by blocking access to `Object` because `Object` isn't accessible
without tricks anyway and it provides some other nasty functions.

BREAKING CHANGE:
This prevents the use of `Object` inside angular expressions.
If you need Object.keys, make it accessible in the scope.
2014-06-30 09:26:29 -07:00
Kristian Hellang 0c80df21b6 fix($http): should not read statusText on IE<10 when request is aborted
Commit 1d2414c introduced a regression by retrieving the statusText
of an aborted xhr request. This breaks IE9, which throws a c00c023f
error when accessing properties of an aborted xhr request. The fix
is similar to the one in commit 6f1050d.
2014-06-30 08:09:59 -07:00
vaibhav kohli 3141dbf179 style(Angular.js): remove extra whitespace 2014-06-29 09:42:34 -07:00
Archer aad502bad8 docs(guide/$location): fix a typo
Change "window.location.path" to "window.location.pathname".

Closes #8012
2014-06-28 20:05:32 -07:00
Elnur Abdurrakhimov dca8972367 docs(Getting Started): fix typo
Closes #8015
2014-06-28 19:42:02 -07:00
rodyhaddad 284de57435 test($interval): add tests making sure $interval uses the methods from $window 2014-06-28 17:35:14 -07:00
Praveen f780ccfa1c fix($interval): when canceling, use clearInterval from $window instead of global scope.
In $interval.cancel, use clearInterval from the $window service instead of from global scope.
The variable clearInterval declared above isn't visible here.
2014-06-28 17:35:06 -07:00
Efthymis Sarbanis 55f99e0710 chore: use triple equals comparison with typeof operator.
It is common practice for typeof operator to be used with '==='.

Closes #8009
2014-06-27 16:53:32 -07:00
Domenic Denicola 1a99ca9c08 docs($q): remove unnecessary $scope.apply wrapping
As of Angular 1.2, this kind of thing is no longer necessary (thank goodness!)
2014-06-26 12:37:04 -07:00
Laurent Curau 37500fca83 docs(guide/unit-testing): correct spelling 2014-06-26 12:37:04 -07:00
rodyhaddad 4fe4fc5abf chore(ngMock): replace misplaced comma with semicolon 2014-06-26 12:32:51 -07:00
rodyhaddad 74e1cc683b fix(jqLite): change expando property to a more unique name
This was causing issue when element === window
A better strategy can be thought of later on.
2014-06-26 12:32:30 -07:00
Igor Minar a4faa5cde7 perf(jqLite): don't use reflection to access expandoId
Since we allow only one copy of Angular to be loaded at a time it doesn't
make much sense randomly generate the expando property name and then be
forced to use slow reflective calles to retrieve the IDs.
2014-06-26 12:32:30 -07:00
Eddie Hedges 32cb40b86d docs(guide/introduction): use durandal as an example of a framework
To me knockout is a library that does data binding well.
Durandal is a framework that uses knockout as it's data binding component.
2014-06-26 12:19:56 -07:00
m-tretyak d1cd677433 docs(srcset): fix mistake in example 2014-06-26 12:08:55 -07:00
thorn0 43c735a816 docs($location): hashPrefix, html5Mode are methods
Closes #7915
2014-06-25 14:48:19 -07:00
Caitlin Potter ab2e83c8c8 fix(input): improve html5 validation support
This CL improves mocking support for HTML5 validation, fixes the behaviour which invokes validators.

Previously, an input would only be revalidated if either its value changed, or if it was the empty
string but did not suffer from bad input --- now, it will be revalidated if either the value has
changed, or the value is the empty string, there is a ValidityState for the element, and that
ValidityState is being tested by one of the validators in the pipeline.

Closes #7937
Closes #7957
2014-06-24 08:35:47 -04:00
Igor Minar e5f454c8af fix(numberFilter): correctly round fractions despite floating-point arithmetics issues in JS
Closes #7870
Closes #7878
2014-06-24 00:37:50 -07:00
Igor Minar 67c11b9a39 fix($injector): check if a fn is an array explicitly
This change makes the code easier to read and also fixes a compatibility issue
with opal.js which pollutes the global state by setting $inject property on
Array prototype

Closes #7904
Closes #2653
2014-06-23 17:20:09 -07:00
Zacky Ma 5a306b7ba3 docs(guide/compiler): change {{user}} to {{user.name}} in example
If user has an `actions` property, it should be an object,
which means if you {{user}}, it'll print out the object.
2014-06-23 13:36:04 -07:00
ephigabay 8ce61bf178 docs(ngModelController): update setValidity
Needs to be `$error[validationErrorKey]!=isValid` and not
`$error[validationErrorKey]=isValid`.

See https://github.com/angular/angular.js/blob/master/src/ng/directive/input.js#L1627

Closes #7934
2014-06-23 13:21:44 -07:00
Chaker Nakhli 9d452bc845 docs(ngSrc): srcset used instead of src for img attribute
In `ngSrc` documentation `srcset` is used instead of `src` as `img` element attribute in the example.

Closes #7951
2014-06-23 13:15:03 -07:00
Julie 192fecc790 chore(grunt): check files in src for ddescribe/iit
Previously, only files in test/ were checked. This does not capture
end to end tests, which are in comments in src/.
2014-06-23 11:28:21 -07:00
Julie 32be6369e4 chore(tests): remove a lingering iit in end to end tests 2014-06-23 11:22:37 -07:00
Shahar Talmi 2a45cea0ba fix(input): escape forward slash in email regexp
This messed up with syntax coloring and variable hovering in chrome developer tools and made debugging really difficult.

Closes #7938
2014-06-22 21:28:55 -04:00
Peter Bacon Darwin ea653e4cdd docs($provide): it is a service not an object
Closes #7917
2014-06-20 17:01:10 +01:00
Alex Muntada 03777445e8 docs(tutorial/step-4): fix e2e test
After a protractor update the test syntax had to be changed.

Closes #7919
2014-06-20 14:36:13 +01:00
Neil Giarratana 8b25ea129a docs(ngPluralize): spell Mary's name correctly
Update ngPluralize.js

Just a silly change to the name of one of the examples that appears to be a typo. Changing Marry to
Mary as the first would be a verb and the latter would be an extremely common name.

Closes #7884
2014-06-17 17:44:17 -04:00
Shahar Talmi d71f16e745 fix(injector): allow multiple loading of function modules
Change HashMap to give $$hashKey also for functions so it will be possible to load multiple module
function instances. In order to prevent problem in angular's test suite,  added an option to HashMap
to maintain its own id counter and added cleanup of $$hashKey from all module functions after each
test.

Before this CL, functions were added to the HashMap via toString(), which could potentially return
the same value for different actual instances of a function. This corrects this behaviour by
ensuring that functions are mapped with hashKeys, and ensuring that hashKeys are removed from
functions and objects at the end of tests.

In addition to these changes, the injector uses its own set of UIDs in order to prevent confusingly
breaking tests which expect scopes or ng-repeated items to have specific hash keys.

Closes #7255
2014-06-16 20:45:49 -04:00
Jason Bedard ed59370d80 fix($compile): bind ng-attr-* even if unbound attribute follows ng-attr-*
Previously, <element ng-attr-foo="{{binding}}" foo="bar"></element>'s "foo" attribute would always
equal "bar", because the bound version was overwritten. This CL corrects this behaviour and ensures
that the ordering of attributes does not have an effect on whether or not ng-attr-bound attributes
do their work.
2014-06-16 20:35:13 -04:00
Ahmad Moussawi d8e5acfe27 docs($sce): update the parseAs method name 2014-06-16 13:46:02 -07:00
James Harrison Fisher af59f4e69a docs(ngMock): fix typo providers -> provides
Should be a verb, ☆.。.:・゜☆MERCI BEAUCOUP☆.。.:・゜☆
2014-06-16 11:47:45 -04:00
Colin Casey 24aee81634 refact(select): use prop to modify the select property
jQuery suggests using `prop` rather than `attr` to modify the `select` property of an element.
You can see the full list of migration warnings for jQuery:
https://github.com/jquery/jquery-migrate/blob/master/warnings.md

Closes #4107
Closes #4122
2014-06-14 17:28:12 +01:00
rodyhaddad f81d56e66c docs(CHANGELOG.md): add changes for 1.2.18 2014-06-13 14:52:28 -07:00
Caitlin Potter f0904cf12e fix(ngResource): don't convert literal values into Resource objects when isArray is true
Previously non-object literals would be thrown out of Resource responses with isArray===true, or
otherwise converted into Objects (in the case of string literals). The reason for this is because
shallowClearAndCopy iterates over keys, and copies keys into the destination. Iterating over String
keys results in integer keys, with a single-character value.

Not converting non-objects to Resources means that you lose the ability to perform Resource operations
on them. However, they become usable as strings, numbers, or booleans, which is important.

In the future, it would be useful to make these useful as Resources while still retaining their primitive
value usefulness.

Closes #6314
Closes #7741
2014-06-13 13:55:33 -07:00
Igor Minar 81b7e5ab0e perf($compile): move ng-binding class stamping for interpolation into compile phase 2014-06-13 13:23:22 -07:00
Igor Minar 1b1890274e perf(ngBind): set the ng-binding class during compilation instead of linking 2014-06-13 13:23:22 -07:00
Igor Minar 6d418ef5e3 perf(jqLite): cache collection length for all methods that work on a single element
This affects jqLite#html, #text, #attr, #prop, #css and others.
2014-06-13 13:23:22 -07:00
Igor Minar 3fa1606c43 chore: name the event callback used by ngClick and friends
This maskes looking at stack traces easier.

Since we generate the callbacks for each event type at runtime and we can't
set function's name because it's read-only, we have to use a generic name.
2014-06-13 13:23:21 -07:00
XrXr 8661a9e3d4 docs(CONTRIBUTING.md): fix link to unit testing docs
The old link points to a page that doesn't exist

Closes #7830
2014-06-13 13:56:28 -04:00
Caitlin Potter cf63292742 test($compile): make IE8 happy
Closes #7828
2014-06-13 12:09:39 -04:00
Peter Bacon Darwin fd420c4061 fix($compile): ensure transclude works at root of templateUrl
If a "replace" directive has an async template, which contains a transclusion
directive at its root node, then outer transclusions were failing to be
passed to this directive.  An example would be uses of `ngIf` inside and
outside the template.

Collaborated with @caitp

Closes #7183
Closes #7772
2014-06-13 12:09:33 -04:00
Vojta Jina 1382d4e88e fix($compile): bound transclusion to correct scope
Nested isolated transclude directives.

This improves/fixes the fix in d414b78717.

See the changed ng-ifunit test: The template inside ng-if should be bound to the
isolate scope of `iso` directive (resp. its child scope). Not to a child of
the root scope. This shows the issue with ng-if. It’s however problem with
other directives too.

Instead of remembering the scope, we pass around the bound parent transclusion.

Conflicts:
	test/ng/directive/ngIfSpec.js
2014-06-13 12:09:33 -04:00
Peter Bacon Darwin b9ddef2a49 fix($compile): don't pass transcludes to non-transclude templateUrl directives 2014-06-13 12:09:32 -04:00
Peter Bacon Darwin eafba9e2e5 fix($compile): don't pass transclude to template of non-transclude directive
If a directive provides a template but is not explicitly requesting transclusion
then the compiler should not pass a transclusion function to the directives
within the template.
2014-06-13 12:09:32 -04:00
Peter Bacon Darwin 6f1d9f8ca6 refactor($compile): no need to use bind 2014-06-13 12:09:32 -04:00
Peter Bacon Darwin bb9310974b fix($compile): fix nested isolated transclude directives
Closes #1809
Closes #7499
2014-06-13 12:09:32 -04:00
Peter Bacon Darwin 30279d7b9b refactor($compile): change parameter name
The boundTransclusionFn that is passed in is really the one from the
parent node.  The change to parentBoundTranscludeFn clarifies this compared
to the childBoundTranscludeFn.
2014-06-13 12:09:32 -04:00
Peter Bacon Darwin 8df5f3259a fix($compile): pass transcludeFn down to nested transclude directives
If you have two directives that both expect to receive transcluded content
the outer directive works but the inner directive never receives a
transclusion function. This only failed if the first transclude directive
was not the first directive found in compilation.

Handles the regression identified in e994259739

Fixes #7240
Closes #7387
2014-06-13 12:09:32 -04:00
Tero Parviainen 14e797c1a1 fix($injector): report circularity in circular dependency error message
Change the error message for a circular dependency to display the full
circle back to the first service being instantiated, so that the problem
is obvious. The previous message stopped one dependency short of the full
circle.

Changes the content of the cdep error message, which may be considered
a breaking change.

Closes #7500
2014-06-12 17:32:28 -07:00
Brian Ford 82cd6b87f0 docs(TRIAGING.md): clarification for issues that are not reproducable 2014-06-12 14:39:04 -07:00
Andreas Krummsdorf 6d7cc572b5 style(loader.js): correct JSDoc tags of the params of the function module(name, requires, configFn)
This will improve the hints for IDE's which support the Google Closure Compiler (e.g. Webstorm)
2014-06-12 13:49:33 -07:00
rodyhaddad 2ebbe00eb5 revert: style(loader.js): correct JSDoc tags of the params of the function module(name, requires, configFn)
This reverts commit f4c08fee85.
2014-06-12 13:49:33 -07:00
Michal Kawalec 8b86d363aa perf($http): move xsrf cookie check to after cache check in $http
$http was previously checking cookies to find an xsrf-token prior to checking
the cache. This caused a performance penalty of about 2ms, which can be very
significant when loading hundreds of template instances on a page.

Fixes #7717
2014-06-12 11:28:00 -07:00
Aiden N 9b51067516 docs(guide/bootstrap): fix link to angular.js script in example
code.angularjs.org/angular.js is 404, updated it

Updated http://code.angularjs.org/angular.js in the example to http://code.angularjs.org/snapshot/angular.js
It works fine now.
2014-06-12 14:24:34 -04:00
fuqcool a3208bf66e docs(guide/services): fix link to services api 2014-06-12 00:13:10 -04:00
Dave Wells 4e1fb82628 docs(errors/$compile/nonassing): fix reversed attribute and scope property names 2014-06-11 14:55:32 -07:00
Alexander Karpan ad466412c6 docs(guide/services): fix link to wikipedia article containing parentheses
Fix in a mis-parsed link with ')' symbol in it
2014-06-10 16:11:16 -04:00
fvanderwielen 299a32740c docs(loader): improve explanation of modules 2014-06-10 11:48:52 -07:00
Rocky Assad eb799bcb71 chore(jshint): dedupe jshint option 2014-06-10 01:46:46 -07:00
Brian Ford 7314c1b69e docs(tutorial/step_09): fix formatting 2014-06-10 01:42:21 -07:00
Brian Ford fcfe2b3793 docs(tutorial/step_09): fix link to filter guide 2014-06-10 01:34:58 -07:00
Kevin Western 5e140a99c7 docs($animate): $animate.enabled's param is optional
The docs show that param 'element' (of type DOMElement) is required when it is optional.
2014-06-10 01:09:42 -07:00
Amar Patel 4da169d15d docs(api/index): add Oxford comma
Verified grammar at https://owl.english.purdue.edu/owl/resource/607/01/
2014-06-10 00:58:02 -07:00
Dylan Semler f37c6f9f73 docs(error/$compile/tplrt): note that html comments can cause this 2014-06-10 00:52:41 -07:00
Carl Sutherland eae658fd96 docs(directive/input): document ngTrim for textarea 2014-06-10 00:38:14 -07:00
Matt Johansen 286f269753 docs(tutorial/step_09): note about 'Filter' suffix
Reminder that 'Filter' is appended to filter names when injected.
Link to Filter guide where this is mentioned.
2014-06-09 22:01:57 -07:00
Stephen Nancekivell 73640a6b7c docs(error/$sce/unsafe): suggest including ngSanatize 2014-06-09 20:55:53 -07:00
Arjunkumar 2dc55ff5c2 docs(guide/index): add codeschool link 2014-06-09 15:50:54 -07:00
Uri Goldshtein 98a2563ec4 docs(guide): add UI-Map to Complementary Libraries 2014-06-09 14:31:49 -07:00
Uri Goldshtein 8c02122837 docs(guide): add ngTagsInput to UI Widgets 2014-06-09 14:02:34 -07:00
Joseph Orbegoso Pea 1e069532fc docs(ngController): improve wording 2014-06-09 13:42:05 -07:00
Nikita Vasilyev 6f6f7e82a4 docs(guide/databinding): add line breaks after images
This looks much better, thanks a bunch @NV
2014-06-08 22:13:53 -04:00
Peter Bacon Darwin d852122442 docs(error/$rootScope/inprog): improve understanding and diagnosis of the error
See #5549
2014-06-08 19:35:13 +01:00
Caitlin Potter 66cb161221 docs(CHANGELOG.md): remove mention of strict-DI
Strict-DI feature was originally merged into v1.2.x, but was reverted by https://github.com/angular/angular.js/commit/373078a94cf3d525b9ae11a2f2876acb6e26f6a3
2014-06-08 02:05:35 -04:00
Sebastian Müller 6c14fb1eb6 perf(isArray): use native Array.isArray
see benchmark: http://jsperf.com/isarray-performance
2014-06-06 20:07:08 -04:00
Peter Bacon Darwin e906aafb0a docs(tutorial): mention additional Debian install step
Thanks to GSC Leticia (gsc-leticia) for identifying this problem.

Closes #7665
2014-06-06 21:28:13 +01:00
Peter Bacon Darwin 6acc73f3e0 chore(CHANGELOG.md): add changes for 1.2.17 2014-06-06 20:13:16 +01:00
Samuel Rats a4367ab00d docs($http): remove duplicate 'to' in withCredentials description
Typo in $http config documentation

Closes #7731
2014-06-06 11:13:48 -04:00
Caitlin Potter 2e0464fba4 test($http): test that timed out $http request rejects promise
Closes #7688
Closes #7686
2014-06-05 20:13:00 -04:00
rodyhaddad 6ffd53ee3c test(jqLite): adapt missed test to new expando name 2014-06-05 14:49:12 -07:00
rodyhaddad 2395bf604d test(jqLite): adapt tests to new expando name 2014-06-05 14:30:44 -07:00
rodyhaddad 2e5fe846e3 chore(jqLite): remove special characters from the expando property
Having special characters in the expando property created a memory bloat.
See https://code.google.com/p/chromium/issues/detail?id=378607#c6 to reproduce

Closes #7701
2014-06-05 13:48:45 -07:00
Wes Alvaro b6388b3f1d docs(misc core): use @kind function instead of @function 2014-06-04 20:42:00 +01:00
Matias Niemelä 669e3aeaa8 docs(ngShow): calirfy info about the .ng-hide class and the display style 2014-06-04 15:17:14 -04:00
Matias Niemelä 55b2f0e862 fix($animate): remove the need to add display:block!important for ngShow/ngHide
Since ngShow/ngHide animations add and remove the .ng-hide class, having to remember
to write display:block on your own is a hassle and leads to problematic animation
code. This fix places a default on the animation for you instead.

Closes #3813
2014-06-04 15:17:14 -04:00
Richard Littauer ca566d8d81 docs(guide/directive): explain controllerAs option
There was nothing about controllerAs in the developer guide.

Helps #6710 and #6759
2014-06-03 17:57:38 -07:00
Juan Manuel Palacios b306babe29 docs(tutorial/step_12): clarify that jQuery should be loaded first
jQuery needs to be loaded before *all* AngularJS modules in the app,
because otherwise AngularJS will not detect the presence of jQuery and
animations  will not work as expected.
2014-06-03 17:48:18 -07:00
Jake Buob d9317cde4f docs(tutorial/step_07): fix typo 2014-06-03 16:41:27 -07:00
Dken 23c8af232f docs(tutorial/index): update requisite version of node
Not all 0.10.x support `^` in versions in `package.json`
2014-06-03 16:36:31 -07:00
Richard Littauer 2fcbd39d0b docs(misc/faq): note that jQuery 2.x currently doesn't work with angular 2014-06-03 16:28:58 -07:00
JMRodriguez24 3ffbf202ce docs(index/api): fix link o templates
Link points to templates. Modified the link label templates instead of types.
2014-06-03 16:26:01 -07:00
Tim Ruffles 09367d88c2 docs(guide/expression): fix docs re $window
The documentation on context is incorrect and misleading:

1. "Angular expressions must use $window explicitly to refer to the global
   `window` object": expressions cannot access `$window`
1. The example doesn't actually attempt to use $window in a expression. It's in a
   function called from an expression, which incorrectly implies to readers that:
  1. functions ARE expressions
  1. functions called by expressions can't access `window`

Here's [a plunkr](http://plnkr.co/edit/Gd4xAV?p=preview) to make both these issues clear.

This change fixes the errors and informs the reader about Angular's `$window` etc services,
and adds an explicit example of an expression not being able to access `window`.
2014-06-03 16:21:28 -07:00
Anuj More 369f69d67a docs(tutorial/index): fix typo 2014-06-03 16:00:00 -07:00
Oivvio Polite 9f43d02af8 docs(guide/providers): fix typo 2014-06-03 15:40:37 -07:00
Oivvio Polite 08e6b88fb2 docs(guide/providers): fix grammar 2014-06-03 14:38:31 -07:00
Isaac Shapira 9227a5db94 fix(ngAnimate): $animate methods should accept native dom elements 2014-06-02 13:58:15 -07:00
Caitlin Potter fc6ce59cd2 chore(ngLocale): update ngLocale scripts 2014-06-02 16:23:20 -04:00
Caitlin Potter 96a314766c fix(ngLocale): fix i18n code-generation to support get_vf_, decimals_, and get_wt_
The updated Closure I18N code relies on these methods to enhance the localization quality.

This fix prevents ngLocale files from referencing undefined values. In the short term, this
means adding references to versions of these methods in locales where they are necessary.
2014-06-02 16:23:20 -04:00
Caitlin Potter 6aa31e17ee chore(ngLocale): change update-closure script to pull from github, not code.google.com
The closure-library migrated a while ago, so the script would fail. This is change
should allow us to update these more frequently.
2014-06-02 16:23:17 -04:00
Phil Westwell d18d5f57c2 docs(*): fix its/it's grammar 2014-05-31 18:47:28 -04:00
zainengineer 2d9e96772f docs(orderBy): add example of directly calling $filter('orderBy')
It's not a bad example of sorting fields in a table, which is something people are frequently wanting
to do. So I say, LGTM!
                        ~caitp, 1988-2014
2014-05-31 18:26:44 -04:00
Caitlin Potter bc2a5aaf05 docs(tutorial): fix minor errors in step 11
I added these when amending the previous commit. My bad ._.
2014-05-31 17:38:38 -04:00
aschokking 4547c11dad docs(tutorial): add karma config update reference to step 11
When including the ng-resource module you appear to need to add a reference to the karma config file
as well or the unit tests will fail. This burned me for a while when going through the tutorial.
2014-05-31 17:33:51 -04:00
Jan c0b360b993 docs(tutorial): add instructions to make experiment render readably in step 5
Update step_05.ngdoc

Closes #7653
2014-05-31 13:20:52 -04:00
dumpweed a659049893 docs(tutorial/step_05): improve explanation of _-prefix 2014-05-30 17:30:58 -07:00
ImaginaryDevelopment a3b9b1d205 docs(ngKeyup): improve example
show implicit `$event` argument
2014-05-30 16:19:04 -07:00
Hallvard Nygård 3305f38db2 docs(CONTRIBUTING.md): fixing link to Google Closure I18N library
The old seems to link to the source code of I18N. Found the same folder on their new Github repo.

"Closure Library's source repository has moved to GitHub.", https://code.google.com/p/closure-library/

Closes #7638
2014-05-30 16:07:10 -04:00
Caitlin Potter 9be4e035d1 style(ngClassSpec): fix indentation to make jscs happy
v1.2.x doesn't run jshint on tests, but if it ever does in the future, we'll want this.
2014-05-30 15:15:22 -04:00
Shahar Talmi 85ce5d0db9 fix(ngClass): support multiple classes in key 2014-05-30 11:56:27 -07:00
rodyhaddad 5c99720934 fix(angular.copy): support circular references in the value being copied
Closes #7618
2014-05-30 11:53:47 -07:00
rodyhaddad 8d26238664 chore(shallowCopy): handle arrays and primitives, and switch to using it where possible
In many cases, we want a shallow copy instead of a full copy

Closes #7618
2014-05-30 11:50:55 -07:00
Paul Jolly b7cb454546 docs($rootScope): fix incorrect docs about how dirty checking is done 2014-05-30 10:33:12 -07:00
Firexion 199825ec26 docs(tutorial): make code samples in step 7 match code in angular-phonecat
Update step_07.ngdoc

Modifying the code snippets provided to match what was on git
2014-05-30 09:58:16 -04:00
Vojta Jina bcdd925c9d style(ngTouch): make lint happy 2014-05-29 14:12:54 -07:00
Carlo s A. Guillen 0bcace309e docs(ngClick): improve style 2014-05-28 18:37:57 -07:00
Pavel Pomerantsev 46c9c942df docs($rootScope): fix incorrect docs and make them clearer
During the first $digest loop after registering a $watch
the listener always run, so the example was incorrect

Closes #7598
2014-05-28 17:40:24 -07:00
Erin Altenhof-Long 2ad439dfc5 docs(ngClick): improve style 2014-05-28 17:33:01 -07:00
Brian Ford 3fbfe3f966 docs($http): use HTTPS URLs in JSONP example 2014-05-28 14:04:55 -07:00
venticello 8ff671753c docs(tutorial/step-12): fix typo
Closes #7596
2014-05-28 10:26:18 -07:00
Peter Bacon Darwin 24092127d1 docs(ngController): add formatting to controller as description and example
Adds to #7591
2014-05-27 22:57:05 +01:00
Richard Littauer f1c7240f04 docs(ngController): add more description of controller as syntax
Using `controller as` in the template is not described well
in the docs, as both `scope` injection and `this` are presented
equally without too much discussion of the advantages of using
either. I added a bit more discussion based on google's internal
style guidelines.

Closes #7591
Closes #5076 (until Angular 2.0 comes out and we refactor everything)
2014-05-27 22:57:05 +01:00
Peter Bacon Darwin fcee3bea1a docs(misc/downloading): fix HTML example formatting
Closes #7060
2014-05-27 22:56:41 +01:00
Matias Niemelä ad08638c0a fix($animate): retain inline styles for property-specific transitions
Transitions that are run through ngAnimate which contain a specific property
cause any inline styles to be erased after the animation is done. This has
something to do with how the browsers handle transitions that do not use
"all" as a transition property.

Closes #7503
2014-05-23 14:46:55 -07:00
Julie 093e76fa15 tests(docsAppE2E): fix race condition flake with switching to new frame
Closes #7569
2014-05-23 11:29:17 -07:00
Juan Manuel Palacios 28c0497524 docs(tutorial): match html from angular-phonecat in step 7 instructions
Place phoneId binding in a proper HTML node

The code where the phoneId binding in the phone-detail.html template is first explained in step 7
of the tutorial doesn't make it a child of a proper HTML node, which makes the end-to-end test
against the view (also introduced in step 7) fail.

The test acquires the binding right from the view (by.binding('phoneId')), and apparently this
operation fails when the binding is not a child of an HTML node, and therefore the entire test also
fails. As soon as the binding is placed inside a <span></span> tag pair, the binding is found and
the test passes. The code on github for step 7 has it right, the binding is within the span tags,
but in the documentation I'm patching here the span's are missing.

☆.。.:*・゜☆ MERCI ☆.。.:*・゜☆
2014-05-23 01:33:07 -04:00
rodyhaddad 88505d8029 refactor($parse): remove the support of JSON parsing mode
It's a feature that isn't exposed to the public, and is
no longer used internally.
2014-05-22 15:22:33 -07:00
Zorigt Bazarragchaa c241a57761 docs(tutorial/index): explain E2E acronym
It was confusing to read "end 2 end" as a numeric two. I kept wondering what two end(s).
Later in the tutorial, the text switched to "End to End" which made more sense than numeric two.
2014-05-22 13:21:16 -07:00
Jesse Palmer b0e985fb67 style: added whitespace
spaces between the ')' and '{' make code a tad easier to read.

Closes #7542
2014-05-22 08:50:59 -07:00
Kevin Aenmey a0dbd95bb9 docs($cacheFactory): fix typo 2014-05-21 16:30:07 -07:00
Tobias Bosch 9fd5450ee8 docs($compile): deprecate replace directives
BREAKING CHANGE:

The `replace` flag for defining directives that
replace the element that they are on will be removed in the next
major angular version.
This feature has difficult semantics (e.g. how attributes are merged)
and leads to more problems compared to what it solves.
Also, with WebComponents it is normal to have custom elements in the DOM.
2014-05-21 16:11:00 -07:00
Max Tobias Weber b5391fae8f docs(tutorial): update code snippet for step 7
replaced bootstrap 2 with bootstrap 3 classes

Closes #7433
2014-05-21 15:54:41 -07:00
Jeff Whelpley b635903ec4 fix($compile): do not merge attrs that are the same for replace directives
If a directives specifies `replace:true` and the template of the directive contains
a root element with an attribute which already exists at the place
where the directive is used with the same value, don't duplicate the value.

Closes #7463
2014-05-21 15:51:48 -07:00
Jesse Palmer c9ee20b64b docs($interpolate): removed function name to match other examples 2014-05-21 15:50:06 -07:00
Freek Wielstra 25ae98ca77 docs($http): clear up Interceptor docs and code
The documentation and code example of $http interceptors is unclear about whether config can be null
or not, and whether the result should always be a promise or not. This pr clears up the documentation
a bit and removes the literal 'or a promise' interpretation of the docs in the code example.

Closes #7431
Closes #7460
2014-05-21 15:36:14 -07:00
NateRedding adb5ee2e0a docs(ngHide): corrected logic in example
Closes #7436
2014-05-21 15:27:01 -07:00
Brice 78954ffcde docs(tutorial): improve instructions for causing test failure (step 2)
Increase readability for test fail line

Closes #6943
2014-05-21 17:32:31 -04:00
specialorange 3b30a4b64a docs(error/$injector/unpr): clarify which code is being referred to in the text
Closes #7020
2014-05-21 22:27:44 +01:00
Edward Brey 866057233c docs(filter): description formatting fix
as it was, the third parameter's description was displayed as
a code block, rather than a bulletted list.
2014-05-21 13:58:22 -07:00
Richard Littauer ec1f4a8c9b test(ngClass): add missing assertions 2014-05-21 13:58:11 -07:00
Tim van den Eijnden c94190139d docs(tutorial): fix controller unit tests to match phonecat / avoid ReferenceError
fix 'ReferenceError: PhoneDetailCtrl is not defined' & 'ReferenceError: PhoneListCtrl is not defined' in Karma unit tests

Closes #7421
2014-05-21 16:38:40 -04:00
Adam Bradley 4896a0b4d4 docs(css): remove Firefox select element drop-down icon
In firefox the version picker's dropdown icon from the default `select` element
is still showing. This CSS forces FF to hide the ugly default.

Closes #6878
2014-05-21 21:34:27 +01:00
kalvn 32bd990eda docs(tutorial): corrected version of jquery installed via bower (step 12)
Corrected the version of jquery in the text content.
2014-05-21 16:31:30 -04:00
James Vanneman 23723298f9 docs($filter): add runnable example
Closes #6871
2014-05-21 21:26:38 +01:00
ABitTooCalm edab80cddb docs(ngStyle): clarify using styles that are not valid property names
Closes #6838
2014-05-21 21:07:54 +01:00
Andrew Mortimer f4bb006e45 docs(guide/controller): fix typo 2014-05-21 12:32:57 -07:00
Kristof Mattei cf3f709889 docs(shallowCopy): fixed typo
Closes #7456
2014-05-21 11:43:02 -07:00
Tobias Bosch e9ecd56dca docs(ngModelController): use $sce and $sanitize in the contenteditable example.
Closes #7464
2014-05-21 11:39:35 -07:00
Tobias Bosch f107ef8bd8 docs(): mention implicit usage of 2014-05-21 11:39:25 -07:00
markau e7eab501db docs(guide/concepts): The service is finance2.js
Closes #7470
2014-05-21 10:58:29 -07:00
Tobias Bosch 97fc47f39e docs(guide/concepts): clarify definitions 2014-05-21 10:58:17 -07:00
Sergei Z 6d1c67727a feat(ngMock): add support of mocha tdd interface
Closes #7489
2014-05-21 10:56:21 -07:00
Erich 8ba78f08b9 docs(guide/concepts): clarify definitions
Closes #7483
2014-05-21 10:56:12 -07:00
Sam Dornan 02a3c31c23 docs(guide/services): fix link to minify Wikipedia page
Closes #7488
2014-05-21 10:55:55 -07:00
Yaron Uliel d4c3d5caaf docs(ngRepeat): fix formatting 2014-05-21 10:28:47 -07:00
Takashi Nakagawa 279f98c4e3 docs(ngModelController): fix indentation code block
Closes #6660
2014-05-21 17:09:13 +01:00
Caitlin Potter 5e548edf67 docs(guide/$location): clarify "$watchers" / "$observers" terminology with links
Add links to API docs for Scope#$watch and Attributes#$observe in $location in order to clarify
the meaning of that terminology.

Closes #7497
2014-05-21 12:00:16 -04:00
Firexion acaf9be685 docs(tutorial): add <span> to index.html to match phonecat step4
Add missing <span> to app/index.html to match actual code on github

☆.。.:*・゜☆ Merci beaucoup! ☆.。.:*・゜☆
2014-05-21 11:29:30 -04:00
GSC Leticia bdd75c97ad docs(tutorial): add instructions for running node in Debian-based distributions
Specifying command for Debian based distributions, like Ubuntu, Mint, etc.

☆.。.:*・゜☆ Fantastique! ☆.。.:*・゜☆
2014-05-21 11:22:47 -04:00
Peter Bacon Darwin a3f1cba8ec docs(guide/expression): mention the ternary operator
Closes #6498
2014-05-21 14:47:46 +01:00
Peter Bacon Darwin 4195b04072 docs($compile): remove reference to ngRepeat providing compile function
ngRepeat no longer has the compile function in its directive definition
object, since it retrieves its transclusion via the link function.

Closes 5638
2014-05-21 14:31:41 +01:00
Peter Bacon Darwin ccc8ec869b docs(tutorial/step-5): update image to match code
Closes #2753
2014-05-21 13:58:48 +01:00
Eli Dalbey 6d8abaedd8 docs(guide/concepts-module-service.png): Typo in image
The ng-app was called ng=app in diagram image.

Closes #6473
Closes #7528
2014-05-21 12:51:26 +01:00
Wes Alvaro fd49d6634c docs(ngRoute): $routeParams is Object.<string, string>
Closes #7386
2014-05-21 12:49:04 +01:00
Ralph Giles cecd5214df docs(*): fix its vs it's typos.
Only use the apostrophe if you can expand "it's" to "it is" and
still have a grammatical phrase.
2014-05-20 17:51:32 -04:00
Gaëtan PRIOUR c5e39c688b docs(tutorial): fixed path to controllersSpec.js file
☆.。.:*・゜☆ DOMO ARIGATO MR ROBOTO ☆.。.:*・゜☆
2014-05-20 12:19:33 -04:00
Igor Minar 240608447a revert: fix($compile): pass transcludeFn down to nested transclude directives
This reverts commit 113850602d.

This change introduced regressions for several scenarios.

reduction: http://jsfiddle.net/5242N/4/
2014-05-19 15:01:19 -07:00
Slava Fomin bcb53deda8 docs(NgAnimate): update the list of supported animations
Closes #7502
2014-05-19 14:24:26 -04:00
Igor Minar 9d4fa33e35 perf($interpolate): optimize value stringification
previously we stringified numbers via toJson which was expensive, I optimized
the code so that toJson is invoked only if really necessary

Closes #7501
2014-05-19 06:35:28 -07:00
Diego Plentz de1461da78 docs(guide/$location) remove duplicate 'Crawling your app' section
The "Crawling your app" section was duplicated.
I just removed the duplication and moved the section to the 'Caveats' section.

Closes #7244
2014-05-19 14:07:36 +01:00
Kebabpizza 2866daf7d6 docs(tutorial): fix link to bower in step 12
Muchas gracias! \o/
2014-05-18 20:48:40 -04:00
Brian Ford b3de37e418 test($compile): use trim helper 2014-05-16 18:19:16 -07:00
Shahar Talmi a4cc9e1944 fix(ngClass): handle index changes when an item is unshifted
Closes #7256
2014-05-16 14:10:38 -07:00
M Alix f8a1c56cad chore($compile): make webstorm's regexp parser happy
Minor change puts \- at end of character pattern

In CLASS_DIRECTIVE_REGEXP and COMMENT_DIRECTIVE_REGEXP, putting the \- character at
the end of the character patter speeds up many IDE parsers and alleviates some
errors in certain IDE's. (WebStorm 8)

Functionally absolutely equivalent. No test change needed.

Closes #7093
2014-05-16 13:12:39 -07:00
Vojta Jina 113850602d fix($compile): pass transcludeFn down to nested transclude directives
If you have two directives that both expect to receive transcluded content
the outer directive works but the inner directive never receives a
transclusion function. This only failed if the first transclude directive
was not the first directive found in compilation.

Fixes #7240
Closes #7387
2014-05-16 13:08:17 -07:00
Jonathan Gotti e76105a320 docs(guide/directives): improve links to isolate scope docs
Link "isolate scope" to "Directive Definition object" section

Closes #7484
2014-05-16 11:23:35 -07:00
Zachary Babtkis 14e9be202a docs(guide/css-styling): tiny grammar fix
Closes #5443
2014-05-16 14:52:31 +01:00
Peter Bacon Darwin dd5215eceb docs(search): fix search submit functionality
When the search input box was submitted (i.e. by pressing enter) the
app was supposed to take you to the first item but this was not happening.
It turns out the app was just reading the wrong property for the path to
the item.

Closes #3078
2014-05-16 14:33:37 +01:00
Peter Bacon Darwin 497ba08775 docs(search): set minimum length to 2
With the minimum search length set to 3, it was not possible to search for `$q`.
Changing this to 2 fixes that without really upsetting the search display, since we
only display the first 40 API and 14 non-API items anyway.

Closes #3078
2014-05-16 14:25:42 +01:00
nderoche eaaf4967f9 docs(ngController): clarify that this is $scope in example
Replace `this` with `$scope` in second example to highlight the fact that
we are working with the `$scope` instead of an instance of the controller
in this example.

Closes #6478
2014-05-16 13:16:43 +01:00
Narretz f440ac7492 chore(docs): fix layout between 769px and 991px
Left nav and main content were tucked slightly under the version picker / breadcrumb navbar

Closes #6474
Closes #7079
2014-05-16 13:09:53 +01:00
linclark d566c4bc61 docs($resource): clarify paramDefaults usage 2014-05-16 12:44:57 +01:00
Peter Bacon Darwin 766b962eac docs(guide/services): add reference to ngmin tool
Closes #5908
2014-05-16 12:34:51 +01:00
Lucas Galfaso 0388eed7e5 fix(numberFilter): fix rounding error edge case
Fix a number rounding error.

Closes #7453
Closes #7478
2014-05-15 21:19:43 +01:00
Christopher Rose 82448b86b5 docs(guide/di): fix typos
Closes #7480
2014-05-15 21:11:54 +01:00
Rich Snapp fafcd6285a fix(jqLite): use jQuery only if jQuery.fn.on present
Make Angular not bind to jQuery versions older than 1.7 since older
versions of jQuery do not support necessary on()/off() methods.
2014-05-12 15:15:21 +02:00
Shahar Talmi 5319621afd fix($compile): set $isolateScope correctly for sync template directives
All isolated scope directives that do not have `templateUrl` were marked
as `$isolateScopeNoTemplate` even if they did have a `template` attribute.

This caused `jqLite#scope()` to return the wrong value for child elements
within the directive's template.

Closes #6942
2014-05-09 14:46:59 +01:00
Caitlin Potter 32aa491588 fix(ngSwitch): properly support case labels with different numbers of transclude fns
Due to a regression introduced several releases ago, the ability for multiple transclude functions
to work correctly changed, as they would break if different case labels had different numbers of
transclude functions.

This CL corrects this by not assuming that previous elements and scope count have the same length.

Fixes 7372
Closes 7373
2014-05-08 17:09:38 -04:00
Thomas Tuts 31bdb60f0a docs(directive): fix misspelled HTML class for an alert
Muchas gracias
2014-05-07 08:00:19 -04:00
barcahead a8aae48bc0 docs($rootScope): use unshift to add items to the array at the beginning
Closes #7364
2014-05-06 21:29:58 -04:00
Mathew Foscarini 517917f9fa docs(minErr): small grammar fix for $compileMinErr ctreq
Closes #7365
2014-05-06 21:27:57 -04:00
Caitlin Potter 1748abe8ef chore(travis): run protractor tests with ff28
FirefoxDriver seems to have an issue with FF29 which is breaking a test case, and causing false negatives.

There is an issue opened on protractor regarding this at https://github.com/angular/protractor/issues/784

Closes #7369
2014-05-06 18:59:05 -04:00
Peter Bacon Darwin 5f5bf07bb8 docs(tutorial): move bower_components into app folder 2014-05-05 20:55:30 +01:00
Yutaka Yamaguchi 3d0b49c07f fix(ngSanitize): encode surrogate pair properly
The encodeEndities function encode non-alphanumeric characters to entities with charCodeAt.
charCodeAt does not return one value when their unicode codeponts is higher than 65,356.
It returns surrogate pair, and this is why the Emoji which has higher codepoints is garbled.
We need to handle them properly.

Closes #5088
Closes #6911
2014-05-02 17:49:33 -04:00
Peter Bacon Darwin b6aec5642e docs(Attributes): ensure code sample is not escaped
Closes #6649
2014-05-02 21:49:44 +01:00
Peter Bacon Darwin e44e5f447b chore(doc-gen): update to dgeni 0.3.0 2014-05-02 16:12:43 +01:00
Chris Rose ca273fd9da docs($injector): fix typos 2014-05-01 15:37:17 -07:00
mjfroehlich 5ff453d422 docs(guide/providers): minor edits 2014-05-01 14:41:02 -07:00
Janas Page d9c75bee93 docs($anchorScroll): minor copyedit.
Singular-tense verb. Definite article.

Closes #7319
2014-04-30 17:50:09 -04:00
Brian Ford e030e64196 chore(package.json): add qq
e0375a61d0 removed qq, but the changelog script still needs it
2014-04-30 14:03:37 -07:00
Peter Bacon Darwin 7ba19cc355 chore(travis-build): don't re-package when testing docs
Since .travis is already running `grunt package` in the `before_script`
block there is no need to run it again when testing the docs.
2014-04-30 11:35:02 +01:00
Brian Ford 21428e5cea chore(travis): use npm cache 2014-04-29 15:33:41 -07:00
Vojta Jina 9321a5f14c chore(travis): update Chrome on SL to 34
For some reason, SL gives us Chrome 28 when no version is specified.
2014-04-29 15:57:18 +02:00
Peter Bacon Darwin 72421b2acf docs(directives): remove line numbers from code blocks 2014-04-29 12:33:45 +01:00
Peter Bacon Darwin c3fe170b8b docs(examples): don't attempt to convert example content from JSON
There are some files in the examples that look like JSON and the default
$http transformResponse handler was trying to convert these from strings
to object. An example was the style.css file in the
https://docs.angularjs.org/api/ng/type/ngModel.NgModelController docs.

This commit fixes this by simply removing this transform when loading
these files.
2014-04-28 22:28:42 +01:00
Uri Goldshtein ed18b8c9da docs(guide): add another analytics library 2014-04-28 12:05:04 -07:00
Edward Brey 0cb276f7ac docs(angular.Module): add link to module.config() docs
Add a link on where to find more info about how to use `module.config()`

Closes #6270
2014-04-28 15:00:18 +01:00
Ryan Hall cfccb8f64a docs(orderBy): clarify how sorting is processed
An API was passing me numbers as strings (ex. '8.25'), and I was noticing
weird sorting behavior with `orderBy` because it was trying to sort the
numbers alphabetically.

Closes #5436
2014-04-28 14:53:55 +01:00
Thomas Tuts 0069f87007 docs(guide/unit-testing): remove unwanted whitespaces
Closes #5395
2014-04-28 14:40:59 +01:00
marcin-wosinek 9599234bae docs(select): improve naming of c variable in example
It was felt that `c` did not make it clear what the variable held. This
has been changed to `color` to match the ng-repeat expression above.
In turn the model value has been changed to `myColor` to prevent a name
collision.

Closes #7210
2014-04-28 14:00:49 +01:00
Tom Yam d423117158 fix(grunt-utils): ensure special inline CSS works when angular is not a global
The build includes a little script to angular.js, which adds some CSS styles to
the page to support things like ngCloak. This script checks that angular is
not in CSP mode, but before this fix assumed that angular would be in the global
scope.

This commit, references `window.angular` instead of just `angular` because when
running angular in an environment where the top-level scope is not the window
(nodejs for example), we angular is actually a property of `window`.

Closes #7176
2014-04-28 13:36:53 +01:00
eydreeyawn 3c8a940686 docs(ngCookies): added example usage of cookieStore
Closes #7278
2014-04-28 08:19:10 -04:00
Caitlin Potter 9f8e30f550 docs(ngCookies): use GFM code-snippet rather than example tag
The example tag creates a big ugly white rectangle on the docs page, and this is not very helpful
and kind of looks bad. So GFM snippets are a better way to go.

This fix also removes the unnecessary example heading from the $cookieStore page, as there has not
been an example use of $cookieStore for 2 years now.

Closes #7279
2014-04-28 07:56:26 -04:00
Peter Bacon Darwin dcd94a23e1 docs(tutorial/step-3): fix experiments
Closes https://github.com/angular/angular-phonecat/issues/142
2014-04-27 10:13:22 +01:00
Peter Bacon Darwin 9b79a00294 docs(tutorial/step-12): add info about app.css changes
Closes https://github.com/angular/angular-phonecat/issues/145
2014-04-27 09:11:06 +01:00
Igor Minar 02058bfbe2 fix($location): don't clobber path during parsing of path
Closes #7199
2014-04-24 23:36:39 -07:00
Michael Payne 76647d3855 docs(guide/di): fix typo
Fixed a typo. "depenendencies" -> "dependencies"

Closes #7232
2014-04-24 13:28:57 -04:00
Søren Louv-Jansen 1f1cad8517 docs(ngMock): fix example for $http respond() helper with function as 1st param
The  `whenPOST` method should return a response object containing status, response body and headers.
If omitted the following error will be thrown:

`Uncaught TypeError: Cannot read property '2' of undefined`

The documentation doesn't make it very clear, so I think it will be appropriate to add it here.

Closes #6761
2014-04-24 09:45:59 -04:00
benjamingr e1f1d65d0c style(Angular.js): remove redundant _angular
Going through the commit history on GitHub, the `_angular` is for noConflict mode,
the case where you have an old reference to a variable called Angular you want to preserve.

Here is the commit that added _angular in : https://github.com/angular/angular.js/commit/
12ba6cec4f

This feature was later removed here:
https://github.com/angular/angular.js/commit/9faabd1ba0b1929785bcf166dc0ff60008e7c442

The variable 'made it through', it's redundant now.

Closes #7215
2014-04-24 11:42:29 +01:00
Peter Bacon Darwin a5df2d4e36 docs(tutorial): clarify bower usage 2014-04-24 10:59:17 +01:00
Peter Bacon Darwin b6514d9e1a docs(ngSwitch): fix formatting of custom usage field 2014-04-24 06:17:43 +01:00
Peter Bacon Darwin 1b1f94d8fe docs(examples): use form POST to create Plunkers
The previous solution for opening Plunkers from the docs relied on tight
coupling between the docs site and the plunkr site, in particular the
URL to the example code on the docs server was hard coded in the Plunker
site.

This change goes back to the old POST method of creating a Plunker, but
with a subtle difference: In the very old docs, the content was injected
directly into the example HTML at build time.  This was easy enough to
do as the example actually ran in the current page but also increased
the size of the doc page.

The new examples are run in completely separate iframes. This new version
of showing a Plunker loads the file content for the Plunker from the
server by accessing the example's manifest.json file using $http requests.

This also has the additional benefit that you can now generate plunkers
from examples that are running locally or, frankly, in any folder on any
server, such as personal builds on the Jenkins CI server.

Closes #7186
Closes #7198
2014-04-24 06:17:42 +01:00
Peter Bacon Darwin 1362a9b456 chore(npm-shrinkwrap): update dependencies
Dgeni-packages is updated to v0.8.3 to fix a bug in the docs (#7184)
Karma is updated to get us the fixed version of chokidar (v0.8.2)

Closes #7184
2014-04-24 06:17:42 +01:00
Peter Bacon Darwin 6a26b2c38c chore(clean-shrinkwrap): chokidar is now fixed at v0.8.2 2014-04-24 06:17:42 +01:00
James deBoer 9ab9bf6b41 perf(scope): 10x. Share the child scope class.
This change causes Scope.$destory to run 10x faster. I suspect
Scope.$new is significantly faster as well, but I didn't measure it.
2014-04-23 13:28:23 -07:00
Caitlin Potter e7e56fe9bf chore(package.json): remove dependencies which are no longer required
Based on https://github.com/angular/angular.js/issues/3244#issuecomment-41003086, I don't believe
we actually use either of these now that dgeni has replaced the old docs app. These should be
removed if Travis is green.

The i18n scripts still rely on q, so unfortunately it can't be gotten rid of just yet.
2014-04-22 16:33:53 -07:00
nnennajohn 85ea376da2 docs(tutorial/index): add directions for installing bower 2014-04-22 16:27:06 -07:00
Amin Ogarrio 050aae3ceb docs(tutorial/step-12): correct file path
Fixed wrong file path:
- angular/angular-animate.js -> angular-animate/angular-animate.js, which meets the code in app/index.html

Closes #7168
2014-04-21 16:21:04 -07:00
Matthew Davies 79d9fd9d57 docs(guide/controller): fixed spelling of spiciness
Closes #7185
2014-04-21 16:03:17 -07:00
ttam3d0 2dc2265e4f docs(tutorial/step_03): sync markup with angular-phonecat
Update from Bootstrap 2.3 to 3.1 changed "span" to "col" tags

Closes #7172
2014-04-21 15:46:57 -07:00
Thomas Junghans 9cd33df50c docs(tutorial): update step_11.ngdoc
Change toEqual to toEqualData in the test 'should create "phones" model with 2 phones fetched from xhr'
to make test more consistent.

Closes #7182
2014-04-21 15:46:46 -07:00
Simon Taranto 1db20ce90f docs(tutorial): update step_07.ngdoc
Closes #7169
2014-04-21 15:32:37 -07:00
Amin Ogarrio 76cb5ce7c5 docs(tutorial): fix typos in examples
The phonecatApp and phonecatAnimations modules have a dot where a semicolon should be at the end of the sentence

Closes #7167
2014-04-21 15:09:18 -07:00
Igor Minar 2a778d0038 chore(jshint): add jshint for the test/ folder 2014-04-18 16:33:15 -07:00
Igor Minar b04d3a8ec6 chore(Scope): name the $watch deregistration function as 2014-04-18 16:32:27 -07:00
jerryfan 7839330b40 docs(tutorial/step_12): fix grammar 2014-04-18 18:43:49 -04:00
Caitlin Potter 2d7cb14a16 fix(input): fix ReferenceError in event listener
Sigh, I ran the tests and they passed... Because I am not running them on IE.

Grumble grumble grumble.
2014-04-18 18:38:20 -04:00
Caitlin Potter f20b06d26d style(input): fix trailing whitespace
Oops. I blame vim for this little accident.
2014-04-18 18:16:03 -04:00
Caitlin Potter 109e5d1d39 fix(input): don't dirty model when input event triggered due to placeholder change
Certain versions of IE inexplicably trigger an input event in response to a placeholder
being set.

It is not possible to sniff for this behaviour nicely as the event is not triggered if
the element is not attached to the document, and the event triggers asynchronously so
it is not possible to accomplish this without deferring DOM compilation and slowing down
load times.

Closes #2614
Closes #5960
2014-04-18 17:48:53 -04:00
Janas Page 227822dac3 docs(form.FormController): fix grammar 2014-04-18 16:46:39 -04:00
Chris Wheatley 92f6b45e02 docs(ngMock): grammar fix
Small grammar fix for mock $httpBackend documentation.
2014-04-18 15:45:37 -04:00
Caitlin Potter 24f7999bc1 fix($location): fix and test html5Mode url-parsing algorithm for legacy browsers
This CL fixes problems and adds test cases for changes from #6421. Changes
include fixing the algorithm for preprocessing href attribute values, as
well as supporting xlink:href attributes. Credit for the original URL
parsing algorithm still goes to @richardcrichardc.

Good work, champ!
2014-04-17 23:48:31 -04:00
Richard Collins e0203660d3 fix($location): make legacy browsers behave like modern ones in html5Mode
Previously, LocationHashbangInHtml5Url, which is used when html5Mode is enabled
in browsers which do not support the history API (IE8/9), would behave very
inconsistently WRT relative URLs always being resolved relative to the app root
url.

This fix enables these legacy browsers to behave like history enabled browsers,
by processing href attributes in order to resolve urls correctly.

Closes #6162
Closes #6421
Closes #6899
Closes #6832
Closes #6834
2014-04-17 23:48:24 -04:00
expilo b6eb5fdb05 docs(tutorial): specify that ng-repeat goes in markup and not script
Just to make clear that it should not go to test spec.

Closes #7104
2014-04-17 12:44:25 -04:00
Thom Allen 5bf6e50b40 docs(tutorial): fix typo in module name
Fixed a typo in step 2

Closes #7138
2014-04-16 16:25:33 -04:00
Caitlin Potter a7ccb7531c fix($httpBackend): don't error when JSONP callback called with no parameter
This change brings Angular's JSONP behaviour closer in line with jQuery's. The feature has
already landed in the 1.3 branch as 6680b7b, however this alternative version is intended
to implement the feature in an IE8-compatible fashion.

Closes #7031
2014-04-15 17:18:24 -04:00
Caitlin Potter 6bea059109 fix($compile): reference correct directive name in ctreq error
Previously, ctreq would possibly reference the incorrect directive name,
due to relying on a directiveName living outside of the closure which
throws the exception, which can change before the call is ever made.

This change saves the current value of directiveName as a property of
the link function, which prevents this from occurring.

Closes #7062
Closes #7067
2014-04-15 17:17:22 -04:00
Caitlin Potter fcdac65aed fix(limitTo): do not convert Infinity to NaN
parseInt(Infinity, 10) will result in NaN, which becomes undesirable when the expected behaviour is
to return the entire input.

I believe this is possibly useful as a way to toggle input limiting based on certain factors.

Closes #6771
Closes #7118
2014-04-15 17:15:15 -04:00
Caitlin Potter 373078a94c revert: feat(injector): "strict-DI" mode which disables "automatic" function annotation
This reverts commit f5a04f59cf.
2014-04-14 20:17:22 -04:00
Caitlin Potter db07ad2d4c docs(ngTouch): define module depending on ngTouch in ngTouch examples
In addition to requiring that the file is loaded, it's also necessary to depend on the ngTouch
module when creating the injector.

Closes #7077
2014-04-14 05:39:08 -04:00
Wojciech Fornal 19d7a127c7 docs(api): fix broken link to "Services" guide
Nothing big. Simply a broken link to "Services".

> Nothing big.

It IS big, don't you ever forget it!

Closes #7101
2014-04-12 20:48:01 -04:00
Caitlin Potter f5a04f59cf feat(injector): "strict-DI" mode which disables "automatic" function annotation
This modifies the injector to prevent automatic annotation from occurring for a given injector.

This behaviour can be enabled when bootstrapping the application by using the attribute
"ng-strict-di" on the root element (the element containing "ng-app"), or alternatively by passing
an object with the property "strictDi" set to "true" in angular.bootstrap, when bootstrapping
manually.

JS example:

    angular.module("name", ["dependencies", "otherdeps"])
      .provider("$willBreak", function() {
        this.$get = function($rootScope) {
        };
      })
      .run(["$willBreak", function($willBreak) {
        // This block will never run because the noMagic flag was set to true,
        // and the $willBreak '$get' function does not have an explicit
        // annotation.
      }]);

    angular.bootstrap(document, ["name"], {
      strictDi: true
    });

HTML:

    <html ng-app="name" ng-strict-di>
      <!-- ... -->
    </html>

This will only affect functions with an arity greater than 0, and without an $inject property.

Closes #6719
Closes #6717
Closes #4504
Closes #6069
Closes #3611
2014-04-11 00:15:32 -04:00
Caitlin Potter ab92da43b0 docs(ngTouch): include angular-touch.js in example iframes
Mystical [deps="angular-touch.js"] is enough to get the correct file to be added to the <head> tag.

Closes #7058
Closes #7074
2014-04-10 14:41:12 -04:00
Valentin Waeselynck 6782c45ddc docs(guide/e2e-testing): remove repeated word 'manually'
Fixed repetition in Caveats paragraph

"manually" was repeated. Grammatical correctness is the prime directive, resistance is futile.

Closes #7073
2014-04-10 11:04:33 -04:00
Julie c55477fb2b docs(e2e-testing): deprecate ng-scenario and update E2E testing doc to discuss protractor 2014-04-10 11:04:25 -04:00
Robert Speicher 2e2d62ca12 docs(tutorial): npm needs "run" keyword for custom script names
Fix "npm run update-webdriver" command

Closes #7071
2014-04-10 08:25:12 -04:00
Steven Benjamin e3141fe5f4 docs(guide/directive): directives can be comments, too
While it's not a widely used feature, and likely shouldn't be recommended, it is
possible to use a directive via a comment node.

Closes #7061
2014-04-10 06:48:06 -04:00
Rosseyn 1ebed26678 docs(guide/ie): fix spelling mistake
Closes #7050
2014-04-08 18:46:53 -04:00
Igor Minar e987efd4c0 docs($location): improve $location.search() docs
Closes #7030
2014-04-07 16:11:25 -07:00
Tyler McGinnis ea72e5f881 docs(ngMock): fix typo
"register" should be "registered"

Closes #7034
2014-04-07 16:34:04 -04:00
Jason Travis c550c12738 docs(guide): fix dropped word in controller description
Closes #7026
2014-04-07 07:46:55 -04:00
Thomas Wicker 651caffe45 docs(tutorial): fix typo in tutorial index page
Spelling error, "server" should be "serve"

Closes #7028
2014-04-07 07:41:02 -04:00
Jonathan Sampson 45855b8ba2 docs(guide/providers): fix grammar in note regarding factory naming conventions
It seems as though this sentence wasn't written the way it was originally planned. I did my best to
approximate the intent of the original author.

Closes #7022
2014-04-06 22:06:34 -04:00
Peter Bacon Darwin feb54d68d2 docs(tutorial/step-8): fix external link 2014-04-06 18:58:28 +01:00
Yiling Lu 2d0f6037f7 docs(tutorial/step-8): link to Protractor rather than ngScenario
Angular test runner API has been deprecated, Protractor is advised:
http://docs.angularjs.org/guide/e2e-testing
Link is updated to direct reader to Protractor API.

Closes #7001
2014-04-06 17:34:57 +01:00
Peter Bacon Darwin ebd9a2a960 chore(docs/app): remove redundant code directive
Closes #7000
2014-04-06 17:31:25 +01:00
Peter Bacon Darwin fcfa6ebb6b docs(guide/di): clarify what can be injected into what
Also do some general housekeeping and tidying of the page.

Closes #6999
2014-04-06 17:25:42 +01:00
Joseph Orbegoso Pea cf8ed01c6e docs(tutorial/step-5): clarify inline annotations
Closes #6998
2014-04-06 15:22:48 +01:00
Peter Bacon Darwin c352b92c40 docs(tutorial/step-7): clarify the new files & modules
Closes #6996
2014-04-06 14:57:19 +01:00
Thiago Colares 369145467c docs(tutorial): added a link to Wiki page on DI in Step 7
This article is fantastic and really helped on understanding how DI works on Angular. It may be
useful to other beginners -- because, at first glance, this topic (DI on Angular) ended a little bit
hazy for me.

Closes #7010
2014-04-05 13:52:37 -04:00
martco c3ec6ea226 docs(guide/directive): grammatical fixup
The 'to' in 'end-to-end' is directional, not numeric

Closes #6895
2014-04-05 09:49:28 -04:00
Jason Carver 291684c29c docs(CONTRIBUTING.md): typo fix
"submitting and issue" should be "submitting an issue"

Closes #7002
2014-04-05 09:46:07 -04:00
Yiling Lu d7615351df docs(tutorial): fix links to bower in Step 11
Minor change: add missing bower reference link.

Closes #7005
2014-04-05 09:36:03 -04:00
Caitlin Potter a97a172ee9 fix($compile): fix regression which affected old jQuery releases
ddb8081 and 4ea57e7 removed the calls which trimmed leading and trailing whitespace from templates
in the HTML compiler. This broke old versions of jQuery (such as 1.9.1), which do not trim
whitespace in their constructors. Naturally, this would not appear in the jQuery tests, as we are
testing against a version which does trim whitespace in the constructor.

This fix re-adds calls to `trim()` when compiling templates in $compile, in order to avoid breaking
old versions of jQuery.
2014-04-05 09:04:23 -04:00
Yiling Lu d53a787f0d docs(tutorial): change regexp so that assertion works
Need to remove this single space for the regex to work here.

Apparently `getText()` is trimming the text content or something, because there is no good reason
why that space should not be there.

Closes #6985
2014-04-04 18:10:49 -04:00
Yiling Lu 9682bd0c4e docs(guide/tutorial): make added assertion one which will actually work.
Update the by.binding usage to make the test case work.

Closes #6987
2014-04-04 16:40:13 -04:00
Matias Niemelä 34d0740350 fix($animate): ensure class-based animations always perform a domOperation if skipped
Closes #6957
2014-04-04 11:47:21 -04:00
Choi YoonSung 4d9efa2f76 docs(tutorial/step-8): module must be loaded in test
Closes #6930
2014-04-04 14:13:18 +01:00
Peter Bacon Darwin f9a7b064a0 docs(tutorial): synchronize with angular-phonecat changes 2014-04-04 14:07:33 +01:00
Peter Bacon Darwin 26ca443c10 chore(docs/app/tutorials): improve helper directives 2014-04-04 14:06:04 +01:00
Peter Bacon Darwin 0f37e49039 docs(tutorial): clean up and elaborate introduction 2014-04-04 10:23:52 +01:00
Peter Bacon Darwin 3fdcde73ae docs(tutorial): synch step 0 with angular-seed 2014-04-04 08:32:25 +01:00
Joseph Orbegoso Pea d2dc77169b docs(guide/scope): small fixes 2014-04-03 16:10:59 -07:00
Martin Jezek d99b506885 docs(tutorial): fix linked files to bower_components folder
Closes #6960
2014-04-03 16:03:26 -07:00
Brian Ford fef0cfc837 chore(CHANGELOG.md): add changelog for 1.2.16 2014-04-03 14:42:19 -07:00
Bobdina 5de845506b chore(build): make version-info.js run on windows
Replaced grep with match
Windows operating systems do not have grep by default

Closes #6912.
2014-04-03 13:47:46 -07:00
Matias Niemelä 38ea542662 fix($animate): ensure the CSS driver properly works with SVG elements
The default CSS driver in ngAnimate directly uses node.className when reading
the CSS class string on the given element. While this works fine with standard
HTML DOM elements, SVG elements have their own DOM property. By switching to use
node.getAttribute, ngAnimate can extract the element's className value without
throwing an exception.

When using jQuery over jqLite, ngAnimate will not properly handle SVG elements
for an animation. This is because jQuery doesn't process SVG elements within it's
DOM operation code by default. To get this to work, simply include the jquery.svg.js
JavaScript file into your application.

Closes #6030
2014-04-03 15:48:08 -04:00
Igor Minar 2db66f5b69 fix(Scope): revert the __proto__ cleanup as that could cause regressions
When a async task interacts with a scope that has been destroyed already
and if it interacts with a property that is prototypically inherited from
some parent scope then resetting proto would make these inherited properties
inaccessible and would result in NPEs
2014-04-03 12:40:42 -07:00
Brian Ford 55fe6d6331 fix(ngClass): handle ngClassOdd/Even affecting the same classes
The basic approach is to introduce a new elt.data() called $classCounts that keeps
track of how many times ngClass, ngClassEven, or ngClassOdd tries to add a given class.
The class is added only when the count goes from 0 to 1, and removed only when the
count hits 0.

To avoid duplicating work, some of the logic for checking which classes
to add/remove move into this directive and the directive calls $animate.

Closes #5271
2014-04-03 11:58:29 -07:00
Andreas Krummsdorf f4c08fee85 style(loader.js): correct JSDoc tags of the params of the function module(name, requires, configFn)
This will improve the hints for IDE's which support the Google Closure Compiler (e.g. Webstorm)
2014-04-03 09:39:29 -07:00
Pascal Precht 71bc451f95 docs(guide): fix link in "Complementary libraries" section
the link to `angular-translate` is outdated. this commit fixes it.
2014-04-03 09:27:51 -07:00
Igor Minar 7e4e696ec3 fix(Scope): more scope clean up on $destroy to minimize leaks
Due to a known V8 memory leak[1] we need to perform extra cleanup to make it easier
for GC to collect this scope object.

V8 leaks are due to strong references from optimized code (fixed in M34) and inline
caches (fix in works). Inline caches are caches that the virtual machine builds on the
fly to speed up property access for javascript objects. These caches contain strong
references to objects so under certain conditions this can create a leak.

The reason why these leaks are extra bad for Scope instances is that scopes hold on
to ton of stuff, so when a single scope leaks, it makes a ton of other stuff leak.

This change removes references to objects that might be holding other big
objects. This means that even if the destroyed scope leaks, the child scopes
should not leak because we are not explicitly holding onto them.

Additionally in  theory we should also help make the current scope eligible for GC
by changing properties of the current Scope object.

I was able to manually verify that this fixes the problem for the following
example app: http://plnkr.co/edit/FrSw6SCEVODk02Ljo8se

Given the nature of the problem I'm not 100% sure that this will work around
the V8 problem in scenarios common for Angular apps, but I guess it's better
than nothing.

This is a second attempt to enhance the cleanup, the first one failed  and was
reverted because it was too aggressive and caused problems for existing apps.
See: #6897

[1] V8 bug: https://code.google.com/p/v8/issues/detail?id=2073

Closes #6794
Closes #6856
Closes #6968
2014-04-03 00:25:48 -07:00
Stephanie Nacios Staub 6da44a4410 docs(tutorial): update instructions for running tests in step 2
Fixing outdated instructions on how to run the test

Closes #6972
2014-04-03 01:02:37 -04:00
Igor Minar a81195c6ca chore(rootScopeSpec): fix a typo in spec description 2014-04-02 21:25:36 -07:00
Yiling Lu 102a3201c1 docs(tutorial): remove reference to old webserver script
script/web-server.js is not present anymore. This doc might be referencing a previous version of the
code. Currently the only way to start the server seems to be using "npm start".

Closes #6966
2014-04-03 00:00:30 -04:00
Jonathan Woodard 59244a7776 docs(guide/bootstrap): remove extra call to angular.module()
There was an extra call to angular.module() not being used in 'getter' mode. While this doesn't
break the demo app, it does look kind of weird, so lets toss it.

Closes #6969
2014-04-02 23:57:16 -04:00
Tobias Bosch 293cb1fc5d docs(ngForm): clarify the purpose of ngForm
Related to #6704 and #2513.
2014-04-02 17:23:42 -07:00
Alexander Harding 81395ac298 test($compile): add tests for <option> or <optgroup> tags as root template nodes 2014-04-02 19:43:08 -04:00
Caitlin Potter ba66c4f3cc refactor(jqLite): IE8-support fixes
ddb8081982 refactors jqLite, and removes support
for IE8. This patch extends this to prevent the CL from breaking IE8, and to
remain suitable for the 1.2.x branch.

Closes #6963
2014-04-02 19:41:28 -04:00
Caitlin Potter 4ea57e7e96 refactor(jqLite): make HTML-parsing constructor more robust
Previously, the jqLite constructor was limited and would be unable to circumvent many of the HTML5
spec's "allowed content" policies for various nodes. This led to complicated and gross hacks around
this in the HTML compiler.

This change refactors these hacks by simplifying them, and placing them in jqLite rather than in
$compile, in order to better support these things, and simplify code.

While the new jqLite constructor is still not even close to as robust as jQuery, it should be more
than suitable enough for the needs of the framework, while adding minimal code.

Closes #6941
Closes #6958
2014-04-02 19:40:56 -04:00
Tero Parviainen 6e420ff28d fix($parse): mark constant unary minus expressions as constant
Previously, constant numbers with a unary minus sign were not treated as constants. This fix corrects
this behaviour, and may provide a small performance boost for certain applications, due to constant
watches being automatically unregistered after their first listener call.

Closes #6932
2014-04-02 10:07:44 -04:00
Julie 5393814756 docs(tutorial): update tutorial steps to discuss protractor
Closes #6940
2014-04-02 08:47:46 -04:00
b9chris fab59e7515 docs($location): fix link to Developer Guide for "Using $location"
Closes #6946
2014-04-02 08:09:45 -04:00
Igor Minar 553c252d5c revert: fix(Scope): aggressively clean up scope on $destroy to minimize leaks
This reverts commit f552f25171.

The commit is causing regressions.

Closes #6897
2014-04-01 16:43:25 -07:00
Peter Bacon Darwin e145a8df72 docs(tutorial): update to match changes to phonecat 2014-04-01 18:22:47 +01:00
Peter Bacon Darwin b49d0cc6e7 docs(css): ensure all type-hints have a background color
If the type of a type-hint was not recognized, say a "Promise", then
the background color was left as white.  Given that the default
foreground color is also white, this meant that such type-hints were
invisible.

Closes #6934
2014-04-01 13:51:15 +01:00
Peter Bacon Darwin 97b171ecb2 chore(grunt): add jscs task to test task
It is too easy to forget to check jscs for things like trailing whitespace
before pushing commits, such as simple doc changes.  This then breaks the
build and is messy.  Adding jscs to the test task gives people a slightly
better chance of catching these before pushing.
2014-04-01 13:51:15 +01:00
Joseph Orbegoso Pea 245de33c00 docs(guide/bootstrap): add note about ngApp and manual bootstrap 2014-03-31 16:58:34 -07:00
Igor Minar 8d4d437e8c fix(Scope): aggressively clean up scope on $destroy to minimize leaks
Due to a known V8 memory leak[1] we need to perform extra cleanup to make it easier
for GC to collect this scope object.

The theory is that the V8 leaks are due to inline caches which are caches
built on the fly to speed up property access for javascript objects.

By cleaning the scope object and removing all properties, we clean up ICs
as well and so no leaks occur.

I was able to manually verify that this fixes the problem for the following
example app: http://plnkr.co/edit/FrSw6SCEVODk02Ljo8se?p=preview

Given the nature of the problem I'm not 100% sure that this will work around
the V8 problem in scenarios common for Angular apps, but I guess it's better
than nothing.

[1] V8 bug: https://code.google.com/p/v8/issues/detail?id=2073

Closes #6794
Closes #6856
2014-03-28 17:23:41 -04:00
mrmrs 7287dbf71d chore(docs): remove px declaration from x,y coordinates in header svg 2014-03-28 17:07:20 -04:00
sgrebnov da88449f25 fix(doc-gen): Run Gulp on Windows too
Using node_module/.bin/gulp will enable to gulp command to run
both on Windows and Linux. In its current form, the default action of
executing a Javascript file on Windows does not use node.
Requires quotes around the command to correctly resolve path on Windows

Closes #6346
2014-03-28 17:07:13 -04:00
Diego Algorta eaf1f8546d docs(faq): fix link to Closure Library
The previous link throws a 404.
2014-03-28 17:07:03 -04:00
John K. Paul 20d926cc45 docs(guide/directive): fix broken link
Fix broken internal link in directive documentation.

Closes #6802
2014-03-28 17:06:52 -04:00
Sekib Omazic 9ae9c1c0da docs(error/ng/btstrpd): fix typo in error page
Minimal typo fix

Closes #6803
2014-03-28 17:06:16 -04:00
Matias Niemelä 8a5972461c chore($animate): fix broken IE8 test 2014-03-28 13:27:30 -04:00
Matias Niemelä 35d635cbcb fix($animate): prevent cancellation timestamp from being too far in the future
Closes #6748
2014-03-28 12:26:13 -04:00
David I. Lehn db2a4c04d6 docs($sce): fix typo.
Closes #6882
2014-03-27 20:28:33 -04:00
tamakisquare 0d62257c5f docs(guide/filter): mention that filters can be used in directives
The doc mentions filters can be used in services and controllers but directives
aren't mentioned. This could lead to confusion for beginners.
2014-03-27 15:37:29 -07:00
Uri Goldshtein f911b84aef docs(guide): add ngStorage to specific topics 2014-03-27 14:31:07 -07:00
jim lyndon 32c09c1d19 feat($http): add xhr statusText to completeRequest callback
Makes xhr status text accessible is $http success/error callback.
See www.w3.org/TR/XMLHttpRequest/#dom-xmlhttprequest-statustext

Closes #2335
Closes #2665
Closes #6713
2014-03-27 17:09:04 -04:00
ChrisRose 26064375ca docs(filter/orderBy): fixed typo 2014-03-27 13:53:49 -07:00
Alex Sanford 7a294369ab docs(ngResource): clarify behaviour of $promise
Closes #6753
2014-03-27 16:36:37 -04:00
winkler1 fbab287ea2 docs(ngShowHide): fix typo 'hrml' -> 'html'
Typo 'hrml'

Oops!

Closes #6874
2014-03-27 14:39:14 -04:00
Narretz 254dcee93d docs(guide/scope): fix links to $interpolate
Closes #6877
2014-03-27 14:33:49 -04:00
William Bagayoko 69e5c369d7 chore(docs): remove unneeded Bootstrap/jQuery files from distribution 2014-03-27 12:33:02 +00:00
wbyoko c0ccbb7b6a docs(error/index): add header
Closes #6849
2014-03-26 17:23:19 -07:00
wbyoko b87713687e docs(misc/index): add header; general links
Closes #6850
2014-03-26 17:23:19 -07:00
wbyoko 950ffb5a84 docs(misc/started): add header
Closes #6851
2014-03-26 17:23:19 -07:00
Narretz 259003056d docs($compile): add note about recursive compilation in templates
Closes #3079
Closes #6869
2014-03-26 16:43:11 -07:00
Tobias Bosch fedc4194d9 chore(release): simplify scripts so that they can be tested locally
The `git fetch --all` resulted in an error if in the local `.gitconfig`
a remote was configured that does not exist in the bower/code.anguarjs.org
repositories (e.g. "remote "upstream-prs"").
2014-03-26 16:28:26 -07:00
Tobias Bosch 16862705e1 chore(release): remove after CDN script
The homepage (angularjs.org) and the docs now calculate the
current cdn version on every build, so there is no need
for an after-cdn script.
2014-03-26 16:28:19 -07:00
Tobias Bosch c694c96e4c chore(release): calculate the cdnVersion on every build
The CDN version of angular is now calculated on every build,
by looking at the tags in angular/angular.js, sorting them
by semver and checking against ajax.googleapis.com which
one is available.
2014-03-26 16:28:02 -07:00
Tobias Bosch 5ac8a6e74a chore(release): don't update phonecat and seed during a release
This is no more needed as phonecat and seed are using bower
now to get the angular version.
2014-03-26 16:26:54 -07:00
Matias Niemelä 0e5106ec2c fix($animate): run CSS animations before JS animations to avoid style inheritance
If a JS animation is run before a CSS animation then the JS animation may end up writing style
data to the element. If any transition or animation style data is written then it may end up
being accidentally inherited into the CSS animation hanlder that ngAnimate uses. This may result
in an unexpected outcome due to the tweaks and hacks that the CSS handler places on the element.
If the CSS animation is run before the JS animation then, if there are no transitions on the style
attribute nor within the global CSS on the page then nothing will happen and the JS animation can
work as expected.

Closes #6675
2014-03-26 12:13:50 -04:00
Igor Minar 9091b77fe6 docs(guide/unit-testing): fix link 2014-03-26 03:50:49 -07:00
Alex Miller 849f998be3 docs(guide/migration): clarify some confusing points
Closes #6756
2014-03-26 03:41:21 -07:00
Nikita Tovstoles 8bc77b68b3 docs(guide/unit-testing): recommend pre-compiling templates
quite a few folks struggle with how to test directives with external templates.
karma-ng-html2js-preprocessor provides an easy solution but the issues is not
raised in the docs.
2014-03-25 17:58:32 -07:00
Brian Ford 95bd046881 docs(guide/filter): fix example style
* use -Controller suffix
* use array annotations
2014-03-25 17:37:08 -07:00
Brian Ford bfce9126e1 docs(guide/directive): fix example style
* use -Controller suffix
* use array annotations
2014-03-25 17:37:01 -07:00
Brian Ford bf2264e2aa docs(error/$injector/unpr): use Controller suffix 2014-03-25 17:13:40 -07:00
Brian Ford 5ced7b20ff docs(guide/controller): use -Controller suffix
Previously, the convention was to end controllers with -Ctrl.
The new convention is to use -Controller
2014-03-25 17:09:15 -07:00
David Pope 114cf9e418 docs($rootScope.Scope): link to angular.equals in Scope.$watch docs 2014-03-25 16:17:24 -07:00
jfortunato 1b61b73f28 docs(tutorial/step_02): fix typo 2014-03-25 15:58:04 -07:00
Brian Ford d657d63a21 docs(ngEventDirs): link to info on $event
Closes #6724
2014-03-25 15:55:37 -07:00
Brian Ford c5bb3a9098 docs(guide/expression): add section on $event 2014-03-25 15:55:26 -07:00
Brian Ford 77edce5ded docs(angular.bootstrap): fix param type to DOMElement 2014-03-25 14:29:01 -07:00
Adam Bradley f37cd4e4ef docs(css): Add background to .type-hint-domelement
`.type-hint-domelement` does not have a background color assigned to it.
DOM element type hints are now proudly displayed with CadetBlue.
2014-03-25 14:29:01 -07:00
Igor Minar 2acc91098b docs(errors/$injector/nomod): add info about forgetting to load the module file
Closes #3752
2014-03-25 14:12:04 -07:00
Caitlin Potter 5b1c89931e docs($cacheFactory): document cache instance methods
These were apparently entirely undocumented. I'm not sure if they're intended
to be private, but in case they're not, I've written some initial docs for them
2014-03-25 13:35:36 -07:00
Patrice Chalin 99a2ad381b chore(CONTRIBUTING): merge relevant updates from angular.dart
Back port changes to angular.dart `CONTRIBUTING.md`, as suggested by
@vicb.
2014-03-25 13:31:01 -07:00
Trevor Ewen 300263abec docs($cacheFactory): add example 2014-03-25 13:28:00 -07:00
Wesley Cho b0bcf18892 docs($compile): add controllerAs example 2014-03-25 13:08:58 -07:00
Emma Guo ea3b6310c9 docs(README): use svg badge 2014-03-25 13:00:59 -07:00
Brian Ford 764a3beecc docs(guide/migration): add header 2014-03-25 12:54:02 -07:00
Brian Ford a603330e7a docs(guide/concepts): improve formatting and clarity 2014-03-25 12:48:23 -07:00
Brian Ford 1f842b1c63 docs(guide/e2e-testing): improve formatting and clarity 2014-03-25 12:48:14 -07:00
Brian Ford 3b09f1bf4e docs(guide/ie): fix header formatting 2014-03-25 12:48:07 -07:00
Brian Ford 561ddc9ff1 docs(guide/i18n): improve content and formatting 2014-03-25 12:25:44 -07:00
Brian Ford 512ecf8f1b docs(guide/ie): note dropping IE8 in 1.3 2014-03-25 11:47:16 -07:00
Uri Goldshtein 6636f1d03f docs(guide): add ui-router to complementary libraries 2014-03-25 14:06:47 -04:00
Teddy Wing 7cccb8b777 docs(ngAnimate): change "&#64" to "@" symbol
Previously, we had problems with code that contained symbols that looked
like jsdoc directives.  This has now been fixed so we can convert these
HTML character codes back to @ signs.

Closes #6822
Closes #6826
2014-03-25 06:55:42 +00:00
Renat Yakubov a275d539f9 fix(filter.ngdoc): Check if "input" variable is defined
By default, "greeting" textfield in this example is prepopulated with "hello" text, but it's pretty easy to copy just filter code to use it in your app. If your textfield is empty while app loads, you'll get an error: "Error: [$interpolate:interr] Can't interpolate: Reverse: {{greeting|reverse}} TypeError: Cannot read property 'length' of undefined". To prevent this, we should check "input" variable, and proceed only in case it is defined.

Closes #6819.
2014-03-24 16:11:28 -07:00
Tobias Bosch 17fa2468bc chore(release): update cdn version 2014-03-24 16:11:27 -07:00
Luke Eller fb2ae5660e docs(guides/directive): add (') to contraction
add apostrophe (') to contraction
2014-03-24 19:09:02 -04:00
cgwyllie 2c4b3573cc docs($http): fix auth default headers example 2014-03-24 19:00:24 -04:00
Caitlin Potter b2363e3102 fix(input): don't perform HTML5 validation on updated model-value
Running html5-validation immediately after model-value is updated is incorrect, because the view
has not updated, and HTML5 constraint validation has not adjusted.

Closes #6796
Closes #6806
2014-03-24 10:57:42 -04:00
Peter Bacon Darwin edfca4c769 chore(npm-shrinkwrap): update dgeni-packages dependency 2014-03-22 22:36:05 +00:00
Vojta Jina a9b5a1087d chore(CHANGELOG): add notes for 1.2.15 2014-03-21 14:58:48 -07:00
Vojta Jina 87b18b9fbe docs(changelog): remove 1.3 notes from 1.2 2014-03-21 14:57:43 -07:00
Caitlin Potter ad128e09ff test($rootScope): add assertion to test ensuring that NaN -> NaN does not throw
https://github.com/angular/angular.js/commit/fb6062fb9d83545730b993e94ac7482ffd43a62c implements a
fix for NaN values causing $watchCollection to throw an infdig error. This change updates the test
by adding an assertion which explains what is actually being tested a bit better, and may also
provide better information in the event that the test ever fails.

Closes #6758
2014-03-21 13:05:29 -07:00
alexgarrett 187b4adbd2 docs(tutorial): correct spelling mistake 2014-03-21 13:05:29 -07:00
Trevor Ewen 375c47d0c0 docs($document): add a documentation example.
The $document docs are pretty empty, and this fills them out a bit. The example itself may not be
particularly useful, but it could be improved or removed later. Works for me.

Closes #6757
2014-03-21 13:05:29 -07:00
thorn0 8fd47a1cd5 docs($q): add mention of Antroid 2.x browser
The Android 2.x browser is not ES5-compatible in that it does not allow
use of reserved words as property names. This docs fix adds Android to the
note to the `$q` docs which already make it known that string property
notation should be used when using the `finally` method on `$q`.
2014-03-21 13:05:29 -07:00
Sekib Omazic e48c28fe92 fix($rootScope): ng-repeat can't handle NaN values. #4605
$watchCollection checks if oldValue !== newValue which does not work for NaN. This was causing
infinite digest errors, since comparing NaN to NaN in $watchCollection would always return false,
indicating that a change was occuring on each loop.

This fix adds a simple check to see if the current value and previous value are both NaN, and
if so, does not count it as a change.

Closes #4605
2014-03-21 13:05:29 -07:00
Caitlin Potter 10d3e1e447 fix(orderBy): support string predicates containing non-ident characters
The orderBy filter now allows string predicates passed to the orderBy filter to make use property
name predicates containing non-ident strings, such as spaces or percent signs, or non-latin
characters.

This behaviour requires the predicate string to be double-quoted.

In markup, this might look like so:

```html
<div ng-repeat="item in items | orderBy:'\"Tip %\"'">
...
</div>
```

Or in JS:

```js
var sorted = $filter('orderBy')(array, ['"Tip %"', '-"Subtotal $"'], false);
```

Closes #6143
Closes #6144
2014-03-21 13:05:29 -07:00
Caitlin Potter 93d1c95c61 fix(ngCookie): convert non-string values to string
Previously, non-string values stored in $cookies would be removed, without warning the user, and
causing difficulty debugging. Now, the value is converted to string before being stored, and the
value is not dropped. Serialization may be customized using the toString() method of an object's
prototype.

Closes #6151
Closes #6220
2014-03-21 13:05:29 -07:00
Chris Constantin 01a34f513b fix(ngTouch): update workaround for desktop Webkit quirk
Fix click busting of input click triggered by a label click quickly
following a touch event on a different element, in desktop
and mobile WebKit

To reproduce the issue fixed by this commit set up a page with
 - an element with ng-click
 - a radio button (with hg-model) and associated label
In a quick sequence tap on the element and then on the label.
The radio button will not be checked, unless PREVENT_DURATION has passed

Closes #6302
2014-03-21 13:05:29 -07:00
frandroid 916e53ce14 docs(tutorial/step_05): fix services link 2014-03-21 11:42:19 -07:00
frandroid b91b3119a4 docs(tutorial/step_05): removed stray "a" 2014-03-21 11:42:18 -07:00
Siddique Hameed 0d60f8d367 fix(angular.bootstrap): only allow angular to load once
This is hard to test as a unit-test, since it involves the actual loading
of angular, but it turns out that it is easy to test using a protractor
e2e test.

Closes #5863
Closes #5587
2014-03-21 11:42:18 -07:00
Peter Bacon Darwin ca69dc6f17 chore(utils): fix version number processing
The changes to version-info meant that the version being injected into
the code at build time was missing the "dot" (patch) version and the
release code-name.
2014-03-21 11:42:18 -07:00
Caitlin Potter 5b7f1bcc00 style($templateCache): remove trailing whitespace
This was introduced by 2ca6d650e8, somewhat inexplicably as I had run
grunt ci-checks locally. But regardless, this should fix this up.
2014-03-21 11:42:18 -07:00
Jesse Palmer 9ab594a66c docs($templateCache): use GFM example format rather than <pre> tags
Updated example formatting.

Closes #6068
2014-03-21 11:42:18 -07:00
Edward Brey 6c82a497c6 docs(loader): add annotations to example 2014-03-21 11:42:18 -07:00
Tyler Kellogg df804406fb docs($cookies): cookies serializer only supports strings
Closes #6705
2014-03-21 11:42:18 -07:00
poshest dadce485a7 docs(errors/$compile/nonassing): update nonassign.ngdoc
It might seem obvious that if you don't supply "bind" attribute in this case, you'll get an error,
but I feel this is worth adding to the doc.

Closes #6725
2014-03-21 11:42:18 -07:00
Sekib Omazic 344cdce136 docs(css): RegExp doesn't have .type-hint-regexp class
type-hint-regexp gets a nice color

closes #6596
2014-03-21 11:42:18 -07:00
Gias Kay Lee f0347d5efa docs(module): add link to mentioned resource
Closes #6628
2014-03-21 11:42:18 -07:00
Gias Kay Lee 1c27e5fc37 docs(css): Fix word breaks issue in <pre>
Closes #6586
2014-03-21 11:42:17 -07:00
wbyoko 5fb298b90f docs(migration): note that services can now return functions
This change mostly effects preprocessed javascript.
2014-03-21 11:42:17 -07:00
Takashi Nakagawa 483325a7b5 chore(formatting): removed unnecessary white spaces 2014-03-21 11:42:17 -07:00
unicodesnowman a86cb7d794 docs(ngView): remove global controller definitions
instead use angular modules
also fix formatting
2014-03-21 11:42:17 -07:00
Neil Johnston c7e60153a5 docs(tutorial/step_02): add experiment to update controller test
Add an experiment to update the controller unit test after modifying it
with the new model property.
2014-03-21 11:42:17 -07:00
Sekib Omazic c0416866f5 docs(booleanAttrs): fix typo 2014-03-21 11:42:17 -07:00
Jan Hancic 8ba452544e docs(tutorial/step_12): link to API docs 2014-03-21 11:42:17 -07:00
David Rogers 8f7f0d26ed docs(ngForm): remove duplicate @param annotation
When the example for `ngAnimate` was added in commit:3344396, the `@param name` annotation was unintentionally duplicated. Remove this duplicate.

Closes #6720
2014-03-21 11:42:17 -07:00
Caitlin Potter 98d825e10d fix(jqLite): traverse host property for DocumentFragment in inheritedData()
If dealing with a document fragment node with a host element, and no parent, use the host
element as the parent. This enables directives within a Shadow DOM or polyfilled Shadow DOM
to lookup parent controllers.

Closes #6637
2014-03-21 11:42:17 -07:00
Mark Jones 57b0d91fd8 docs(ngInclude): make the quote type explicit 2014-03-21 11:42:17 -07:00
linclark 9226b36572 docs($http): update shortcut method description
Update docs to reflect that $http no longer requires passing in an HTTP method, as changed in #6401.
2014-03-21 11:42:16 -07:00
bradwheel 39635fd0d7 docs(ngRoute): remove global controller syntax in the example 2014-03-21 11:42:16 -07:00
Igor Minar cad307fa1f docs(triaging): correct information about milestones 2014-03-21 11:42:16 -07:00
Denis Parchenko 78bc84c497 docs(guide/module): remove duplicate word
Closes #6709
2014-03-21 11:42:16 -07:00
Peter Bacon Darwin 1f2750136e docs(runnableExamples): add "edit in Plunker" button
The "runnableExample.template.html" template overrides the one in the
dgeni-packages "examples" package with a similar template that also has
a link to a special Plunker URL that can pull in the example from our
code.angularjs.org website.
2014-03-21 11:42:16 -07:00
Peter Bacon Darwin 5b93e5fcfc chore(shrinkwrap): grunt-jasmine-node is retrieved from github 2014-03-21 11:42:16 -07:00
Caitlin Potter 770fd5a917 docs(misc/contribute): make anchor links work properly
Closes #6706
2014-03-21 11:42:16 -07:00
Brian Andersen 4b29186696 docs(tutorial): fix broken link
On page http://docs.angularjs.org/tutorial/step_05 link is broken.

Should point to http://docs.angularjs.org/guide/services NOT http://docs.angularjs.org/guide/dev_guide.services

Closes #6714
2014-03-21 11:42:16 -07:00
Tobias Bosch 7b5be9ee29 chore(CHANGELOG.md): add changelog for 1.3.0-beta.3 2014-03-21 11:33:17 -07:00
Jeff Cross eeb261bcd5 chore: update changelog for 1.3.0-beta.2 2014-03-21 11:33:05 -07:00
Tobias Bosch ef88a8a020 chore(CHANGELOG.md): add input type date PR as breaking change
Related to #6630
2014-03-21 11:32:54 -07:00
Tobias Bosch 86ab885fd9 chore(release): fix angularjs.org cdn script 2014-03-20 14:33:14 -07:00
Peter Bacon Darwin de07ddeac6 chore(angularjs.org/publish.sh): align release script with new website
Closes #6690
2014-03-20 14:33:14 -07:00
Jeff Balboni dc149de936 fix(select): avoid checking option element selected properties in render
In Firefox, hovering over an option in an open select menu updates the selected property of option
elements. This means that when a render is triggered by the digest cycle, and the list of options
is being rendered, the selected properties are reset to the values from the model and the option
hovered over changes. This fix changes the code to only use DOM elements' selected properties in a
comparison when a change event has been fired. Otherwise, the internal new and existing option
arrays are used.

Closes #2448
Closes #5994
Closes #6769
2014-03-20 17:27:02 -04:00
Vojta Jina 320f6d1214 chore(scripts): fix the versions script again 2014-03-20 14:03:55 -07:00
Vojta Jina 1517d6d2f2 chore(scripts): fix the versions script 2014-03-20 14:03:49 -07:00
Vojta Jina 6bb17af2e3 chore(scripts): disable testing seed and phonecat during a release
This reverts commit d5294ebfa0.

It turned out to be more work and I don't wanna deal with it right now.
2014-03-20 14:03:41 -07:00
Vojta Jina 505ead7e58 chore(scripts): test seed and phonecat during a release 2014-03-20 14:03:35 -07:00
Vojta Jina 1da4e89385 chore(scripts): make the release script more flexible
Now the SHA can be short/long, whateva.
2014-03-20 14:03:28 -07:00
Chirayu Krishnappa 83f37d78ba fix(version-info): explicitly specify the remote
`git ls-remote --tags` assumes that you have a remote set up for your
current branch.  That isn't the case, at least for me, when I'm working
on local branches.  `grunt write` doesn't do the right thing in that
case (`git ls-remote --tags` bails out and the silent: true param makes
this a pain to debug.)  Prefer explicit to implicit.

Closes #6678.
2014-03-20 13:58:44 -07:00
Brett Porter d4ac25496a test(ngMock): workaround issue with negative timestamps
In some specific timezones and operating systems, it seems that
getTimezoneOffset() can return an incorrect value for negative timestamps, as
described in #5017. While this isn't something easily fixed in the mock code,
the tests can avoid that particular timeframe by using a positive timestamp.

Closes #5017
Closes #6730
2014-03-18 21:31:20 -07:00
Traxmaxx e84da2283c fix($$RAFProvider): check for webkitCancelRequestAnimationFrame
Android 4.3 only supports webkitCancelRequestAnimationFrame.

Closes #6526
2014-03-18 21:38:20 -04:00
Igor Minar 3dd9572754 fix(Scope): $watchCollection should call listener with oldValue
Originally we destroyed the oldValue by incrementaly copying over portions of the newValue
into the oldValue during dirty-checking, this resulted in oldValue to be equal to newValue
by the time we called the watchCollection listener.

The fix creates a copy of the newValue each time a change is detected and then uses that
copy *the next time* a change is detected.

To make `$watchCollection` behave the same way as `$watch`, during the first iteration
the listener is called with newValue and oldValue being identical.

Since many of the corner-cases are already covered by existing tests, I refactored the
test logging to include oldValue and made the tests more readable.

Closes #2621
Closes #5661
Closes #5688
Closes #6736
2014-03-18 12:01:42 -07:00
Igor Minar 922cb7e42f chore(log): add log.empty() method to the testing logger
`log.empty()` is the same as `log.reset()`, except thati `empty()`  also returns the current array with messages

instead of:

```
// do work
expect(log).toEqual(['bar']);
log.reset();
```

do:

```
// do work
expect(log.empty()).toEqual(['bar']);
```
2014-03-18 12:01:35 -07:00
Peter Bacon Darwin 103cb513d9 docs(guide/concepts): move ng-app into example text
Closes #6639
2014-03-18 07:14:06 +00:00
Peter Bacon Darwin c24e4e4ed5 chore(package.json): update dgeni-packages dependency 2014-03-18 07:14:06 +00:00
Peter Bacon Darwin 1b46a7dcdf chore(version-info): previousVersions should not return undefined
Closes #6702
2014-03-18 07:13:43 +00:00
Emile Silvis 8d28d65b36 docs(guide/tutorial): make capitalization of "Angular" consistent
- step_05.ngdoc
- step_06.ngdoc
- step_07.ngdoc
- step_08.ngdoc

Closes #6686
Closes #6687
Closes #6688
Closes #6689
2014-03-16 09:52:51 -07:00
Bruno Baia fbb125a3af fix($http): allow sending Blob data using $http
Closes #5012
2014-03-16 09:52:44 -07:00
Igor Minar ca7336391a chore(package.json): update karma to 0.12.0 2014-03-16 09:52:14 -07:00
Peter Bacon Darwin 771bccc35c chore(clean-shrinkwrap): add a utility to clean up the shrinkwrap file
This is to deal with https://github.com/npm/npm/issues/3581

See the previous commit for more info.

Closes #6672
2014-03-16 09:52:04 -07:00
Igor Minar c794b96bdc chore(npm): clean up shrinkwrap file, remove unused properties
from our experiements it appears that the presense or absense of the from and resolved properties
makes no difference on the behavior of  but  updates these properties
with different values depending on different state of the cache and node_modules.

So in order to get clean diffs during updates, we are just going to drop these properties and have
a script to do this automatically.

Long term this should be fixed in npm: https://github.com/npm/npm/issues/3581
2014-03-16 09:51:42 -07:00
Pawel Kozlowski f108a2a994 fix($http): don't covert 0 status codes to 404 for non-file protocols
PR #5547 introduced conversion of all 0 status codes to 404 for cases
where no response was recieved (previously this was done for the
file:// protocol only). But this mechanism is too eager and
masks legitimate cases where status 0 should be returned. This commits
reverts to the previous mechanism of handling 0 status code for the
file:// protocol (converting 0 to 404) while retaining the returned
status code 0 for all the protocols other than file://

Fixes #6074
Fixes #6155
2014-03-14 13:45:07 -07:00
Nick Heiner 7cbf61cabb docs(ngMock): grammar nitpick. 2014-03-14 11:50:48 -07:00
Sagie Maoz dfdb72559f docs(guide/compiler): add missing closing parenthesis 2014-03-14 11:50:37 -07:00
Nick Carter d69793d93c docs(guide/unit-testing): fix typo 2014-03-14 11:50:28 -07:00
Wesley Cho b068c8b605 docs($resource): fix example using promise 2014-03-14 11:50:19 -07:00
Thomas Belin ec16352579 fix (ngAnimate): fix requestAnimationFrame for old version of Firefox
The recent $$RAFProvider which is a wrapper for the native
requestAnimationFrame method doesn't use the mozRequestAnimationFrame.
Old versions of FF (20 for example) crash if ngAnimate is included

No breaking changes and fix issue https://github.com/angular/angular.js/issues/6535

Closes #6535
Closes #6540
2014-03-14 11:50:05 -07:00
Peter Bacon Darwin aa4ba23350 chore(doc-gen): fix dependencyPath 2014-03-14 11:49:01 -07:00
Peter Bacon Darwin 25e639b474 chore(package.json): update dgeni-packages dependency
The new version of dgeni-packages/ngdoc generates a manifest for each
example that can be used by plunker.
2014-03-14 11:48:07 -07:00
Matias Niemelä ee8e4a946e fix($$rAF): always fallback to a $timeout incase native rAF isn't supported
Closes #6654
2014-03-14 13:48:37 -04:00
Tomer Chachamu a41a2a1d2c fix(ngAnimate): setting classNameFilter disables animation inside ng-if
Closes #6539
2014-03-14 13:48:29 -04:00
Peter Bacon Darwin eadd8d08d3 docs(scripts/utils.inc): clarify documentation 2014-03-14 11:12:13 +00:00
Peter Bacon Darwin 602a1142e8 chore(shrinkwrap): update dgeni-packages 2014-03-13 20:31:44 +00:00
Peter Bacon Darwin 0b7fef3d94 chore(shrinkwrap): re-run shrinkwrap locally
This will make the following commit clearer when the update is run.
2014-03-13 20:31:44 +00:00
Tobias Bosch 809d47ec77 chore(version-info): use remote tags and increment patch version 2014-03-12 17:33:52 -07:00
Peter Bacon Darwin f3444d495d chore(version-info): better error msg if not tags 2014-03-12 17:33:41 -07:00
Igor Minar 612c882b83 chore(npm): add shrinkwrap to lock down dependencies
We need to be able to build angular at older shas, without the lock file / shrinkwrap file
the dependencies will resolve differently on different machines and at different times.

This will help us avoid broken builds and hard to track down issues.

I had to manually edit this file after it was generated because `npm shrinkwrap` will install
optional dependencies as if they were hard dependencies.

See: https://github.com/npm/npm/issues/2679#issuecomment-37361236

My manual edit:

```
diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json
index 756df44..dc157eb 100644
--- a/npm-shrinkwrap.json
+++ b/npm-shrinkwrap.json
@@ -3110,19 +3110,7 @@
         "chokidar": {
           "version": "0.8.1",
           "from": "https://registry.npmjs.org/chokidar/-/chokidar-0.8.1.tgz",
-          "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-0.8.1.tgz",
-          "dependencies": {
-            "fsevents": {
-              "version": "0.1.6",
-              "from": "fsevents@0.1.6",
-              "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-0.1.6.tgz"
-            },
-            "recursive-readdir": {
-              "version": "0.0.2",
-              "from": "recursive-readdir@0.0.2",
-              "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-0.0.2.tgz"
-            }
-          }
+          "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-0.8.1.tgz"
         },
         "glob": {
           "version": "3.2.9",
```

Additionally chokidar doesn't list the dependencies above as optional, but that will hopefully
be soon fixed: https://github.com/paulmillr/chokidar/pull/106

In the meantime the patch from the PR above needs to be applied to
node_modules/karma/node_modules/chokidar/package.json before running `npm shrinkwrap`

----

After this change is applied, angular core developers don't need to do anything differently,
except when updating dependencies we need to call `npm update && npm shrinkwrap --dev`
followed by reappling my patch above until npm's bug.

Closes #6653
2014-03-11 22:46:54 -07:00
Igor Minar f2a6be3129 chore(build): don't instruct Jenkins test on IE
for an unknown reason the VMs can't connect to local karma, so all builds on Jenkins (ci.angularjs.org)
are failing right now.

Since we want to kill Jenkins anyway, and travis tests on IE, this should not have any
significant impact on us.

Conflicts:
	jenkins_build.sh
2014-03-11 10:43:36 -07:00
Louis Haußknecht 465663ed77 docs(route.js): changed html entities lt gt to < and > 2014-03-11 10:40:57 -07:00
Basem Mostafa 1102ffaaf8 docs(ngRepeat): Separate animation class in new lines
Moving to new lines & making it bold to avoid confusion
when they r all in same line without any separation

Closes #6633
2014-03-11 10:40:51 -07:00
Matias Niemelä 98f6a82390 chore(docs): ensure the "Improve this doc" button is clickable
Closes #6631
2014-03-11 10:40:45 -07:00
doodeec a43c6e1828 docs($route): change routes property to correct type
change $route.routes property type to Object, property is marked incorrectly as an Array

Closes #6552
2014-03-11 10:40:39 -07:00
Narretz 0db301f863 docs(guide/forms): remove unnecessary controller reference
the controller reference was breaking the custom validation example

Closes #6525
Closes #6533
2014-03-11 10:40:32 -07:00
chadfennell 8e6d3875c6 docs(guide/providers): remove unneeded word "the"
no need to specify which space, there's only one :)

Closes #6622
2014-03-11 10:40:21 -07:00
Chung-Min Cheng b9d77d46ff docs(tutorial/step-12): correct application name
Fixed wrong app name:
- phonecat -> phonecatApp, which meets the code in app.js

Closes #6611
2014-03-11 10:40:12 -07:00
Peter Bacon Darwin 96f94d4347 docs(Error404): better heading 2014-03-11 10:40:05 -07:00
Peter Bacon Darwin 63831f118f docs(Error404): improve search results layout 2014-03-11 10:39:59 -07:00
Peter Bacon Darwin ebe280eede docs(404 errors): provide a better 404 experience
It is a bit rough and ready but does a better job than nothing.
2014-03-11 10:39:47 -07:00
Brian Ford 95d6cdc7c7 docs(changelog): release notes for 1.3.0-beta.1 retractable-eyebrow 2014-03-11 10:36:08 -07:00
Sekib Omazic 9223215add docs($sce): correct typo
`consititute` -> `constitute`

Typo fixed

Closes #6607
2014-03-11 10:35:59 -07:00
Igor Minar 309cfd109f chore(build): upgrade grunt-jscs-checker to ~0.4.0
this is primarily to resolve peerdependency version mismatch issue
2014-03-11 10:35:51 -07:00
Sekib Omazic cfc6175aab docs(ngBind): fix typo
`preferrable` -> `preferable`

Typo fixed

Closes #6606
2014-03-11 10:35:42 -07:00
Igor Minar dc39f368c3 docs(guide/migration): fix broken link 2014-03-11 10:35:34 -07:00
Sekib Omazic c0f3400573 docs(guide/migration): fix typos
A few typos fixed.

Closes #6605
2014-03-11 10:35:27 -07:00
Sekib Omazic 822d7e5ae9 docs(guide/directive): fix typo
`restictions` -> `restrictions`

Closes #6604
2014-03-11 10:35:18 -07:00
Stéphane Reynaud 5874db84ab docs(tutorial): display button icons (Previous, Live Demo, ...)
In relation to https://github.com/angular/dgeni-packages/pull/8

Closes #6641
2014-03-11 10:21:32 +00:00
Peter Bacon Darwin e9e8d49216 style(jsdoc tags): remove/ammend invalid tags
As highlighted by the new sterner dgeni.
2014-03-11 10:16:38 +00:00
Peter Bacon Darwin 550fc21ce5 chore(build): refactor build version information 2014-03-11 06:54:52 +00:00
Peter Bacon Darwin a8aba8957b docs(versions): rework the version info extraction
The docs were relying on the grunt/util module for getting version info
but this was unreliable and full of custom regexes.  This is moved into
a new version-info module that makes much better use of the semver library.
2014-03-11 06:54:52 +00:00
Lucas Galfasó ca0ac64997 fix($compile): support templates with thead and tfoot root elements
If the first element in a template is a <thead> or a <tfoot>, then
use the existing logic to handle table elements compilation.

Closes #6289
2014-03-07 15:09:16 -08:00
Peter Bacon Darwin 7678501bc9 chore(package): update dgeni dependencies 2014-03-07 15:09:11 -08:00
Peter Bacon Darwin dec5eb6e83 chore(doc-gen): add contentFolder config property 2014-03-07 15:09:06 -08:00
Peter Bacon Darwin 2eff326781 chore(doc-gen): add inline @type tag 2014-03-07 15:09:01 -08:00
Peter Bacon Darwin 50ce5746a7 docs($route): fix formatting of example code 2014-03-07 15:08:55 -08:00
Peter Bacon Darwin 1537f80267 chore(doc-gen): fix error-doc processor
The meta-data should be parsed from the name not the id.
2014-03-07 15:08:50 -08:00
Peter Bacon Darwin 021d3aa21a chore(doc-gen): improve error reporting 2014-03-07 15:08:42 -08:00
Eddie Hedges e8c8c5459e docs(tutorial): link update for Jasmine
Jasmine doesn't live at the replaced link anymore.
It has a link to click through, but I figured it would be better
to just go directly to the correct location.

Closes #6591
2014-03-07 15:08:37 -08:00
Misha Moroshko 1c20aed318 docs(guide/services): minor fixes 2014-03-07 15:08:16 -08:00
Chirayu Krishnappa 4c4d24a338 chore(publish.sh): publish to all serving backends 2014-03-07 15:05:30 -08:00
Timothée Jeannin 8c7b9b8de4 style: enable jscs requireLeftStickedOperators rule
Closed #6544.
2014-03-07 15:05:22 -08:00
Tony Bergeron f39ac571c4 docs(directive.ngdoc): typo fix 2014-03-07 15:04:44 -08:00
tpiere 84f36701bc docs(tutorial): update step_09.ngdoc
Closes #5991
2014-03-07 15:04:37 -08:00
Zak Johnson 6d4ce240de docs(guide/services): clean up typos 2014-03-07 15:04:30 -08:00
mgerstenblatt 229a155aef docs(guide/forms): fix a typo
Closes #6556
2014-03-07 15:04:24 -08:00
Chung-Min Cheng 73250089cd docs(tutorial): update step_08.ngdoc
Closes #6537
2014-03-07 15:04:16 -08:00
Sharon DiOrio a72bc4e69f docs(tutorial/index): improve accessibility
- Adds accessibility attributes to links and images.
- Adds a note on using NVM for node.
2014-03-07 15:04:08 -08:00
Takashi Nakagawa 0812061274 chore(grunt): remove unnecessary white spaces 2014-03-07 15:03:57 -08:00
597 changed files with 14540 additions and 51637 deletions
-1
View File
@@ -14,7 +14,6 @@ angular.js.tmproj
angular.xcodeproj
.idea
.agignore
.lvimrc
libpeerconnection.log
npm-debug.log
/tmp/
+15 -732
View File
@@ -921,77 +921,6 @@ jQuery. We don't expect that app code actually depends on this accidental featur
<a name="1.3.0-beta.11"></a>
# 1.3.0-beta.11 transclusion-deforestation (2014-06-06)
## Bug Fixes
- **$animate:** remove the need to add `display:block !important` for `ngShow`/`ngHide`
([7c011e79](https://github.com/angular/angular.js/commit/7c011e79d8b3d805755181ace472883800234bf4),
[#3813](https://github.com/angular/angular.js/issues/3813))
- **$compile:**
- bound transclusion to correct scope
([56c60218](https://github.com/angular/angular.js/commit/56c60218d1e70e3a47e37193a4a48714eeda7d44))
- set the iteration state before linking
([0c8a2cd2](https://github.com/angular/angular.js/commit/0c8a2cd2da3a4a9f5d2ee9c25ea8ed56d74a93ab))
- don't pass transcludes to non-transclude templateUrl directives
([2ee29c5d](https://github.com/angular/angular.js/commit/2ee29c5da81ffacdc1cabb438f5d125d5e116cb9))
- don't pass transclude to template of non-transclude directive
([19af0397](https://github.com/angular/angular.js/commit/19af0397456eb8fc06dea47145fdee0e38e62f81))
- fix nested isolated transclude directives
([d414b787](https://github.com/angular/angular.js/commit/d414b787173643362c0c513a1929d8e715ca340e),
[#1809](https://github.com/angular/angular.js/issues/1809), [#7499](https://github.com/angular/angular.js/issues/7499))
- pass transcludeFn down to nested transclude directives
([1fef5fe8](https://github.com/angular/angular.js/commit/1fef5fe8230e8dc53f2c9f3f510a35cf18eeab43),
[#7240](https://github.com/angular/angular.js/issues/7240), [#7387](https://github.com/angular/angular.js/issues/7387))
- **$parse:** fix parsing error with leading space and one time bind
([24c844df](https://github.com/angular/angular.js/commit/24c844df3b6d80103b01e4847b2d55b082757feb),
[#7640](https://github.com/angular/angular.js/issues/7640))
- **angular.copy:** support circular references in the value being copied
([083f496d](https://github.com/angular/angular.js/commit/083f496d46415c01fec6dfa012da63235d0996e4),
[#7618](https://github.com/angular/angular.js/issues/7618))
- **angular.toJson:** only strip properties beginning with `$$`, not `$`
([c054288c](https://github.com/angular/angular.js/commit/c054288c9722875e3595e6e6162193e0fb67a251))
- **ngAnimate:**
- `$animate` methods should accept native DOM elements
([222d4737](https://github.com/angular/angular.js/commit/222d47370e585d9de9fa842310734ba1dd895fab))
- fix property name that is used to calculate cache key
([9f5c4370](https://github.com/angular/angular.js/commit/9f5c4370489043ed953c102340ce203a822c8b42),
[#7566](https://github.com/angular/angular.js/issues/7566))
- **ngClass:** support multiple classes in key
([7eaaca8e](https://github.com/angular/angular.js/commit/7eaaca8ef2b3db76b7c87e98d264d4b16d90a392))
- **ngIf:** ensure that the correct (transcluded) scope is used
([d71df9f8](https://github.com/angular/angular.js/commit/d71df9f83cd3882295ca01b1bb8ad7fb024165b6))
- **ngLocale:** fix i18n code-generation to support `get_vf_`, `decimals_`, and `get_wt_`
([cbab51ca](https://github.com/angular/angular.js/commit/cbab51cac5d6460938e4dfe0035d624df2208d6c))
- **ngRepeat:** ensure that the correct (transcluded) scope is used
([b87e5fc0](https://github.com/angular/angular.js/commit/b87e5fc0920915991122ba5dac87b619847b3568))
- **ngShow:** ensure that the display property is never set to `block`
([1d90744f](https://github.com/angular/angular.js/commit/1d90744f4095ee202616a30f5d6f060fc8e74b20),
[#7707](https://github.com/angular/angular.js/issues/7707))
## Features
- **$resource:** allow props beginning with `$` to be used on resources
([d3c50c84](https://github.com/angular/angular.js/commit/d3c50c845671f0f8bcc3f7842df9e2fb1d1b1c40))
## Breaking Changes
- **$resource:** due to [d3c50c84](https://github.com/angular/angular.js/commit/d3c50c845671f0f8bcc3f7842df9e2fb1d1b1c40),
If you expected `$resource` to strip these types of properties before,
you will have to manually do this yourself now.
- **angular.toJson:** due to [c054288c](https://github.com/angular/angular.js/commit/c054288c9722875e3595e6e6162193e0fb67a251),
If you expected `toJson` to strip these types of properties before,
you will have to manually do this yourself now.
<a name="1.2.17"></a>
# 1.2.17 - quantum disentanglement (2014-06-06)
@@ -1089,427 +1018,6 @@ jQuery. We don't expect that app code actually depends on this accidental featur
<a name="1.3.0-beta.10"></a>
# 1.3.0-beta.10 excessive-clarification (2014-05-23)
## Bug Fixes
- **$animate:** retain inline styles for property-specific transitions
([98b9d68e](https://github.com/angular/angular.js/commit/98b9d68ea3ecfb521e9279c9cbfe93f8ba7d626e),
[#7503](https://github.com/angular/angular.js/issues/7503))
- **$compile:** do not merge attrs that are the same for replace directives
([1ab6e908](https://github.com/angular/angular.js/commit/1ab6e908b15470d59b52eb0ead20c755c66ec3b8),
[#7463](https://github.com/angular/angular.js/issues/7463))
- **$parse:** remove deprecated promise unwrapping
([fa6e411d](https://github.com/angular/angular.js/commit/fa6e411da26824a5bae55f37ce7dbb859653276d))
- **Scope:** $broadcast and $emit should set event.currentScope to null
([82f45aee](https://github.com/angular/angular.js/commit/82f45aee5bd84d1cc53fb2e8f645d2263cdaacbc),
[#7445](https://github.com/angular/angular.js/issues/7445), [#7523](https://github.com/angular/angular.js/issues/7523))
- **ngModel:** do not dirty the input on $commitViewValue if nothing was changed
([facd904a](https://github.com/angular/angular.js/commit/facd904a613e716151a13ab7460b5e6206e0442b),
[#7457](https://github.com/angular/angular.js/issues/7457), [#7495](https://github.com/angular/angular.js/issues/7495))
## Features
- **$interpolate:** escaped interpolation expressions
([e3f78c17](https://github.com/angular/angular.js/commit/e3f78c17d3b5d3a714402d7314094aabe7f6512a),
[#5601](https://github.com/angular/angular.js/issues/5601), [#7517](https://github.com/angular/angular.js/issues/7517))
- **{{ bindings }}:** lazy one-time binding support
([cee429f0](https://github.com/angular/angular.js/commit/cee429f0aaebf32ef1c9aedd8447a48f163dd0a4),
[#7486](https://github.com/angular/angular.js/issues/7486), [#5408](https://github.com/angular/angular.js/issues/5408))
- **ngMock:** add support of mocha tdd interface
([854bf5b7](https://github.com/angular/angular.js/commit/854bf5b74d0395f4d2e30382102d3f5d1614ea11),
[#7489](https://github.com/angular/angular.js/issues/7489))
## Performance Improvements
- **$interpolate:** optimize value stringification
([e927193d](https://github.com/angular/angular.js/commit/e927193de06500f01a2f893934250911cf1905e6),
[#7501](https://github.com/angular/angular.js/issues/7501))
## Breaking Changes
- **$compile:** due to [eec6394a](https://github.com/angular/angular.js/commit/eec6394a342fb92fba5270eee11c83f1d895e9fb), The `replace` flag for defining directives that
replace the element that they are on will be removed in the next major angular version.
This feature has difficult semantics (e.g. how attributes are merged) and leads to more
problems compared to what it solves. Also, with Web Components it is normal to have
custom elements in the DOM.
- **$parse:** due to [fa6e411d](https://github.com/angular/angular.js/commit/fa6e411da26824a5bae55f37ce7dbb859653276d),
promise unwrapping has been removed. It has been deprecated since 1.2.0-rc.3.
It can no longer be turned on.
Two methods have been removed:
* `$parseProvider.unwrapPromises`
* `$parseProvider.logPromiseWarnings`
- **Scope:** due to [82f45aee](https://github.com/angular/angular.js/commit/82f45aee5bd84d1cc53fb2e8f645d2263cdaacbc),
[#7445](https://github.com/angular/angular.js/issues/7445),
[#7523](https://github.com/angular/angular.js/issues/7523)
`$broadcast` and `$emit` will now reset the `currentScope` property of the event to
null once the event finished propagating. If any code depends on asynchronously accessing their
`currentScope` property, it should be migrated to use `targetScope` instead. All of these cases
should be considered programming bugs.
<a name="1.3.0-beta.9"></a>
# 1.3.0-beta.9 release-naming (2014-05-16)
## Bug Fixes
- **$compile:** pass `transcludeFn` down to nested transclude directives
([4f03dc5a](https://github.com/angular/angular.js/commit/4f03dc5a9650f3f22f78b438474322b4b8871dec),
[#7240](https://github.com/angular/angular.js/issues/7240), [#7387](https://github.com/angular/angular.js/issues/7387))
- **jqLite:** use jQuery only if jQuery.fn.on present
([e9bc51cb](https://github.com/angular/angular.js/commit/e9bc51cb0964ea682c1654919174dacebd09fcf6))
- **ngClass:** handle index changes when an item is unshifted
([5fbd618c](https://github.com/angular/angular.js/commit/5fbd618c2ff0dbaa4e19d0fd0e55921ce7d89478),
[#7256](https://github.com/angular/angular.js/issues/7256))
- **ngMessages:** annotate ngMessages controller for minification
([0282ca97](https://github.com/angular/angular.js/commit/0282ca971df7923c8f3dba0eb0df544e244e5b93))
- **numberFilter:** fix rounding error edge case
([81d427b5](https://github.com/angular/angular.js/commit/81d427b5f0d3502f65e8db5beaa5ad837c9ede17),
[#7453](https://github.com/angular/angular.js/issues/7453), [#7478](https://github.com/angular/angular.js/issues/7478))
## Features
- **ngTouch:** add optional `ngSwipeDisableMouse` attribute to `ngSwipe` directives to ignore mouse events.
([5a568b4f](https://github.com/angular/angular.js/commit/5a568b4f960cc5381b3911e3a6423aff2ff7f7f9),
[#6627](https://github.com/angular/angular.js/issues/6627), [#6626](https://github.com/angular/angular.js/issues/6626))
## Breaking Changes
- **jqLite:** due to [d71dbb1a](https://github.com/angular/angular.js/commit/d71dbb1ae50f174680533492ce4c7db3ff74df00),
the jQuery `detach()` method does not trigger the `$destroy` event.
If you want to destroy Angular data attached to the element, use `remove()`.
<a name="1.3.0-beta.8"></a>
# 1.3.0-beta.8 accidental-haiku (2014-05-09)
## Bug Fixes
- **$compile:** set $isolateScope correctly for sync template directives
([562c4e42](https://github.com/angular/angular.js/commit/562c4e424b0ed5f8d4bffba0cd18e66db2059043),
[#6942](https://github.com/angular/angular.js/issues/6942))
- **$httpBackend:** Add missing expectHEAD() method
([e1d61784](https://github.com/angular/angular.js/commit/e1d6178457045e721872022f71227b277cb88726),
[#7320](https://github.com/angular/angular.js/issues/7320))
- **$interpolate:** don't ReferenceError when context is undefined
([924ee6db](https://github.com/angular/angular.js/commit/924ee6db06a2518224caada86769efedd21c0710),
[#7230](https://github.com/angular/angular.js/issues/7230), [#7237](https://github.com/angular/angular.js/issues/7237))
- **grunt-utils:** ensure special inline CSS works when `angular` is not a global
([af72f40a](https://github.com/angular/angular.js/commit/af72f40a5512daa97c1f175a59b547c33cff1dc0),
[#7176](https://github.com/angular/angular.js/issues/7176))
- **injector:** invoke config blocks for module after all providers
([c0b4e2db](https://github.com/angular/angular.js/commit/c0b4e2db9cbc8bc3164cedc4646145d3ab72536e),
[#7139](https://github.com/angular/angular.js/issues/7139), [#7147](https://github.com/angular/angular.js/issues/7147))
- **ngModelOptions:**
- enable overriding the default with a debounce of zero
([c56e32a7](https://github.com/angular/angular.js/commit/c56e32a7fa44e2edd2c70f663906720c7c9ad898),
[#7205](https://github.com/angular/angular.js/issues/7205))
- initialize ngModelOptions in prelink
([fbf5ab8f](https://github.com/angular/angular.js/commit/fbf5ab8f17d28efeadb492c5a252f0778643f072),
[#7281](https://github.com/angular/angular.js/issues/7281), [#7292](https://github.com/angular/angular.js/issues/7292))
- **ngSanitize:** encode surrogate pair properly
([627b0354](https://github.com/angular/angular.js/commit/627b0354ec35bef5c6dbfab6469168c2fadcbee5),
[#5088](https://github.com/angular/angular.js/issues/5088), [#6911](https://github.com/angular/angular.js/issues/6911))
- **ngSrc, ngSrcset:** only interpolate if all expressions are defined
([8d180383](https://github.com/angular/angular.js/commit/8d180383014cbe38d58ff3eab083f51cfcfb8dde),
[#6984](https://github.com/angular/angular.js/issues/6984))
- **ngSwitch:** properly support case labels with different numbers of transclude fns
([ac37915e](https://github.com/angular/angular.js/commit/ac37915ef64c60ec8f8d4e49e4d61d7baeb96ba0),
[#7372](https://github.com/angular/angular.js/issues/7372), [#7373](https://github.com/angular/angular.js/issues/7373))
## Features
- **$compile:** allow SVG and MathML templates via special `type` property
([f0e12ea7](https://github.com/angular/angular.js/commit/f0e12ea7fea853192e4eead00b40d6041c5f914a),
[#7265](https://github.com/angular/angular.js/issues/7265))
- **$interpolate:** add optional allOrNothing param
([c2362e3f](https://github.com/angular/angular.js/commit/c2362e3f45e732a9defdb0ea59ce4ec5236fcd3a))
- **FormController:** commit `$viewValue` of all child controls when form is submitted
([a0ae07bd](https://github.com/angular/angular.js/commit/a0ae07bd4ee8d98654df4eb261d16ca55884e374),
[#7017](https://github.com/angular/angular.js/issues/7017))
- **NgMessages:** introduce the NgMessages module and directives
([0f4016c8](https://github.com/angular/angular.js/commit/0f4016c84a47e01a0fb993867dfd0a64828c089c))
## Breaking Changes
- **$http:** due to [ad4336f9](https://github.com/angular/angular.js/commit/ad4336f9359a073e272930f8f9bcd36587a8648f),
Previously, it was possible to register a response interceptor like so:
```js
// register the interceptor as a service
$provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {
return function(promise) {
return promise.then(function(response) {
// do something on success
return response;
}, function(response) {
// do something on error
if (canRecover(response)) {
return responseOrNewPromise
}
return $q.reject(response);
});
}
});
$httpProvider.responseInterceptors.push('myHttpInterceptor');
```
Now, one must use the newer API introduced in v1.1.4 (4ae46814), like so:
```js
$provide.factory('myHttpInterceptor', function($q) {
return {
response: function(response) {
// do something on success
return response;
},
responseError: function(response) {
// do something on error
if (canRecover(response)) {
return responseOrNewPromise
}
return $q.reject(response);
}
};
});
$httpProvider.interceptors.push('myHttpInterceptor');
```
More details on the new interceptors API (which has been around as of v1.1.4) can be found at
https://docs.angularjs.org/api/ng/service/$http#interceptors
- **injector:** due to [c0b4e2db](https://github.com/angular/angular.js/commit/c0b4e2db9cbc8bc3164cedc4646145d3ab72536e),
Previously, config blocks would be able to control behaviour of provider registration, due to being
invoked prior to provider registration. Now, provider registration always occurs prior to configuration
for a given module, and therefore config blocks are not able to have any control over a providers
registration.
**Example**:
Previously, the following:
```js
angular.module('foo', [])
.provider('$rootProvider', function() {
this.$get = function() { ... }
})
.config(function($rootProvider) {
$rootProvider.dependentMode = "B";
})
.provider('$dependentProvider', function($rootProvider) {
if ($rootProvider.dependentMode === "A") {
this.$get = function() {
// Special mode!
}
} else {
this.$get = function() {
// something else
}
}
});
```
would have "worked", meaning behaviour of the config block between the registration of "$rootProvider"
and "$dependentProvider" would have actually accomplished something and changed the behaviour of the
app. This is no longer possible within a single module.
- **ngModelOptions:** due to [adfc322b](https://github.com/angular/angular.js/commit/adfc322b04a58158fb9697e5b99aab9ca63c80bb),
This commit changes the API on `NgModelController`, both semantically and
in terms of adding and renaming methods.
* `$setViewValue(value)` -
This method still changes the `$viewValue` but does not immediately commit this
change through to the `$modelValue` as it did previously.
Now the value is committed only when a trigger specified in an associated
`ngModelOptions` directive occurs. If `ngModelOptions` also has a `debounce` delay
specified for the trigger then the change will also be debounced before being
committed.
In most cases this should not have a significant impact on how `NgModelController`
is used: If `updateOn` includes `default` then `$setViewValue` will trigger
a (potentially debounced) commit immediately.
* `$cancelUpdate()` - is renamed to `$rollbackViewValue()` and has the same meaning,
which is to revert the current `$viewValue` back to the `$lastCommittedViewValue`,
to cancel any pending debounced updates and to re-render the input.
To migrate code that used `$cancelUpdate()` follow the example below:
Before:
```js
$scope.resetWithCancel = function (e) {
if (e.keyCode == 27) {
$scope.myForm.myInput1.$cancelUpdate();
$scope.myValue = '';
}
};
```
After:
```js
$scope.resetWithCancel = function (e) {
if (e.keyCode == 27) {
$scope.myForm.myInput1.$rollbackViewValue();
$scope.myValue = '';
}
}
```
<a name="v1.3.0-beta.7"></a>
# v1.3.0-beta.7 proper-attribution (2014-04-25)
## Bug Fixes
- **$location:** don't clobber path during parsing of path
([498835a1](https://github.com/angular/angular.js/commit/498835a1c4d0dc6397df4dd667796b09565fedf4),
[#7199](https://github.com/angular/angular.js/issues/7199))
## Performance Improvements
- **scope:** ~10x speedup from sharing the child scope class.
([8377e818](https://github.com/angular/angular.js/commit/8377e81827a840b9eb64f119de4bcbaba0ceb3be))
<a name="v1.3.0-beta.6"></a>
# v1.3.0-beta.6 expedient-caffeination (2014-04-21)
## Bug Fixes
- **$animate:** ensure class-based animations always perform a domOperation if skipped
([708f2ba9](https://github.com/angular/angular.js/commit/708f2ba9843b665e417b93c7df907194565db991),
[#6957](https://github.com/angular/angular.js/issues/6957))
- **$compile:**
- reference correct directive name in ctreq error
([1192531e](https://github.com/angular/angular.js/commit/1192531e9b48cd90cbb601b0c0fdeb12340c1885),
[#7062](https://github.com/angular/angular.js/issues/7062), [#7067](https://github.com/angular/angular.js/issues/7067))
- fix regression which affected old jQuery releases
([ef64169d](https://github.com/angular/angular.js/commit/ef64169db32ffdf5e0e3ae2154ac434c6a55378b))
- **$location:**
- fix and test html5Mode url-parsing algorithm for legacy browsers
([49e7c32b](https://github.com/angular/angular.js/commit/49e7c32bb45ce3984df6768ba7b2f6a723a4ebe7))
- make legacy browsers behave like modern ones in html5Mode
([3f047704](https://github.com/angular/angular.js/commit/3f047704c70a957596371fec554d3e1fb066a29d),
[#6162](https://github.com/angular/angular.js/issues/6162), [#6421](https://github.com/angular/angular.js/issues/6421), [#6899](https://github.com/angular/angular.js/issues/6899), [#6832](https://github.com/angular/angular.js/issues/6832), [#6834](https://github.com/angular/angular.js/issues/6834))
- **input:** don't dirty model when input event triggered due to placeholder change
([ff428e72](https://github.com/angular/angular.js/commit/ff428e72837c85b9540ee9e5a3daa2c9477c90bb),
[#2614](https://github.com/angular/angular.js/issues/2614), [#5960](https://github.com/angular/angular.js/issues/5960))
- **limitTo:** do not convert Infinity to NaN
([5dee9e4a](https://github.com/angular/angular.js/commit/5dee9e4a33ab2a0be6d8a8099297be3028771e0b),
[#6771](https://github.com/angular/angular.js/issues/6771), [#7118](https://github.com/angular/angular.js/issues/7118))
- **ngModelController:** introduce $cancelUpdate to cancel pending updates
([940fcb40](https://github.com/angular/angular.js/commit/940fcb4090e96824a4abc50252aa36aaf239e937),
[#6994](https://github.com/angular/angular.js/issues/6994), [#7014](https://github.com/angular/angular.js/issues/7014))
## Features
- **$resource:** Make stripping of trailing slashes configurable.
([3878be52](https://github.com/angular/angular.js/commit/3878be52f6d95fca4c386d4a5523f3c8fcb04270))
- **Scope:** add `$watchGroup` method for observing a set of expressions
([21f93163](https://github.com/angular/angular.js/commit/21f93163384f36fc4ae0934387339380e3dc3e9c))
- **injector:** "strict-DI" mode which disables "automatic" function annotation
([4b1695ec](https://github.com/angular/angular.js/commit/4b1695ec61aac8de7fcac1dfe8b4b420f9842c38),
[#6719](https://github.com/angular/angular.js/issues/6719), [#6717](https://github.com/angular/angular.js/issues/6717), [#4504](https://github.com/angular/angular.js/issues/4504), [#6069](https://github.com/angular/angular.js/issues/6069), [#3611](https://github.com/angular/angular.js/issues/3611))
- **ngModelOptions:** custom triggers and debounce of ngModel updates
([dbe381f2](https://github.com/angular/angular.js/commit/dbe381f29fc72490f8e3a5328d5c487b185fe652),
[#1285](https://github.com/angular/angular.js/issues/1285))
## Performance Improvements
- **$compile:** watch interpolated expressions individually
([0ebfa0d1](https://github.com/angular/angular.js/commit/0ebfa0d112c8ba42242cb8353db91e93eb42b463))
- **$interpolate:** speed up interpolation by recreating watchGroup approach
([546cb429](https://github.com/angular/angular.js/commit/546cb429d9cea25a9bdadbb87dfd401366b0b908))
## Breaking Changes
- **$interpolate:** due to [88c2193c](https://github.com/angular/angular.js/commit/88c2193c71954b9e7e7e4bdf636a2b168d36300d),
the function returned by `$interpolate`
no longer has a `.parts` array set on it.
Instead it has two arrays:
* `.expressions`, an array of the expressions in the
interpolated text. The expressions are parsed with
`$parse`, with an extra layer converting them to strings
when computed
* `.separators`, an array of strings representing the
separations between interpolations in the text.
This array is **always** 1 item longer than the
`.expressions` array for easy merging with it
<a name="1.3.0-beta.5"></a>
# 1.3.0-beta.5 chimeric-glitterfication (2014-04-03)
## Bug Fixes
- **$animate:**
- insert elements at the start of the parent container instead of at the end
([1cb8584e](https://github.com/angular/angular.js/commit/1cb8584e8490ecdb1b410a8846c4478c6c2c0e53),
[#4934](https://github.com/angular/angular.js/issues/4934), [#6275](https://github.com/angular/angular.js/issues/6275))
- ensure the CSS driver properly works with SVG elements
([c67bd69c](https://github.com/angular/angular.js/commit/c67bd69c58812da82b1a3a31d430df7aad8a50a8),
[#6030](https://github.com/angular/angular.js/issues/6030))
- **$parse:** mark constant unary minus expressions as constant
([7914d346](https://github.com/angular/angular.js/commit/7914d3463b5ec560c616a0c9fd008bc0e3f7c786),
[#6932](https://github.com/angular/angular.js/issues/6932))
- **Scope:**
- revert the `__proto__` cleanup as that could cause regressions
([71c11e96](https://github.com/angular/angular.js/commit/71c11e96c64d5d4eb71f48c1eb778c2ba5c63377))
- more scope clean up on $destroy to minimize leaks
([d64d41ed](https://github.com/angular/angular.js/commit/d64d41ed992430a4fc89cd415c03acf8d56022e6),
[#6794](https://github.com/angular/angular.js/issues/6794), [#6856](https://github.com/angular/angular.js/issues/6856), [#6968](https://github.com/angular/angular.js/issues/6968))
- **ngClass:** handle ngClassOdd/Even affecting the same classes
([c9677920](https://github.com/angular/angular.js/commit/c9677920d462046710fc72ca422ab7400f551d2e),
[#5271](https://github.com/angular/angular.js/issues/5271))
## Breaking Changes
- **$animate:** due to [1cb8584e](https://github.com/angular/angular.js/commit/1cb8584e8490ecdb1b410a8846c4478c6c2c0e53),
`$animate` will no longer default the after parameter to the last element of the parent
container. Instead, when after is not specified, the new element will be inserted as the
first child of the parent container.
To update existing code, change all instances of `$animate.enter()` or `$animate.move()` from:
`$animate.enter(element, parent);`
to:
`$animate.enter(element, parent, angular.element(parent[0].lastChild));`
<a name="1.2.16"></a>
# 1.2.16 badger-enumeration (2014-04-03)
@@ -1556,169 +1064,6 @@ to:
[#2335](https://github.com/angular/angular.js/issues/2335), [#2665](https://github.com/angular/angular.js/issues/2665), [#6713](https://github.com/angular/angular.js/issues/6713))
<a name="1.3.0-beta.4"></a>
# 1.3.0-beta.4 inconspicuous-deception (2014-03-28)
## Bug Fixes
- **$animate:**
- prevent cancellation timestamp from being too far in the future
([ff5cf736](https://github.com/angular/angular.js/commit/ff5cf736e5b8073c8121295743873ccd04cc7d6b),
[#6748](https://github.com/angular/angular.js/issues/6748))
- make CSS blocking optional for class-based animations
([1bebe36a](https://github.com/angular/angular.js/commit/1bebe36aa938890d61188762ed618b1b5e193634),
[#6674](https://github.com/angular/angular.js/issues/6674), [#6739](https://github.com/angular/angular.js/issues/6739))
- run CSS animations before JS animations to avoid style inheritance
([2317af68](https://github.com/angular/angular.js/commit/2317af68510fe3b67526282dad697ad4dc621a19),
[#6675](https://github.com/angular/angular.js/issues/6675))
- **Scope:** aggressively clean up scope on $destroy to minimize leaks
([f552f251](https://github.com/angular/angular.js/commit/f552f25171390e726ad7246ed18b994970bcf764),
[#6794](https://github.com/angular/angular.js/issues/6794), [#6856](https://github.com/angular/angular.js/issues/6856))
- **doc-gen:** Run Gulp on Windows too
([47ba6014](https://github.com/angular/angular.js/commit/47ba60146032c0bfadeaa9f3816644b31fc33315),
[#6346](https://github.com/angular/angular.js/issues/6346))
- **filter.ngdoc:** Check if "input" variable is defined
([4a6d4de5](https://github.com/angular/angular.js/commit/4a6d4de53ed1472c0cb2323292127495619d7ed9),
[#6819](https://github.com/angular/angular.js/issues/6819))
- **input:** don't perform HTML5 validation on updated model-value
([b472d027](https://github.com/angular/angular.js/commit/b472d0275f2900beba3b1f2fcee821369f8c15c1),
[#6796](https://github.com/angular/angular.js/issues/6796), [#6806](https://github.com/angular/angular.js/issues/6806))
## Features
- **$http:** add xhr statusText to completeRequest callback
([1d2414ca](https://github.com/angular/angular.js/commit/1d2414ca93a0340840ea1e80c48edb51ec55cd48),
[#2335](https://github.com/angular/angular.js/issues/2335), [#2665](https://github.com/angular/angular.js/issues/2665), [#6713](https://github.com/angular/angular.js/issues/6713))
## Breaking Changes
- **$animate:** due to [1bebe36a](https://github.com/angular/angular.js/commit/1bebe36aa938890d61188762ed618b1b5e193634),
Any class-based animation code that makes use of transitions
and uses the setup CSS classes (such as class-add and class-remove) must now
provide a empty transition value to ensure that its styling is applied right
away. In other words if your animation code is expecting any styling to be
applied that is defined in the setup class then it will not be applied
"instantly" unless a `transition:0s none` value is present in the styling
for that CSS class. This situation is only the case if a transition is already
present on the base CSS class once the animation kicks off.
Before:
.animated.my-class-add {
opacity:0;
transition:0.5s linear all;
}
.animated.my-class-add.my-class-add-active {
opacity:1;
}
After:
.animated.my-class-add {
transition:0s linear all;
opacity:0;
}
.animated.my-class-add.my-class-add-active {
transition:0.5s linear all;
opacity:1;
}
Please view the documentation for ngAnimate for more info.
<a name="1.3.0-beta.3"></a>
# 1.3.0-beta.3 emotional-waffles (2014-03-21)
## Bug Fixes
- **ngAnimate:** support `webkitCancelRequestAnimationFrame` in addition to `webkitCancelAnimationFrame`
([c839f78b](https://github.com/angular/angular.js/commit/c839f78b8f2d8d910bc2bfc9e41b3e3b67090ec1),
[#6526](https://github.com/angular/angular.js/issues/6526))
- **$http:** allow sending Blob data using `$http`
([b8cc71d4](https://github.com/angular/angular.js/commit/b8cc71d476f76ff51e719fb76fb2348027c858ce),
[#5012](https://github.com/angular/angular.js/issues/5012))
- **$httpBackend:** don't error when JSONP callback is called with no parameter
([6680b7b9](https://github.com/angular/angular.js/commit/6680b7b97c0326a80bdccaf0a35031e4af641e0e),
[#4987](https://github.com/angular/angular.js/issues/4987), [#6735](https://github.com/angular/angular.js/issues/6735))
- **$rootScope:** ng-repeat can't handle `NaN` values. #4605
([fb6062fb](https://github.com/angular/angular.js/commit/fb6062fb9d83545730b993e94ac7482ffd43a62c),
[#4605](https://github.com/angular/angular.js/issues/4605))
- **$rootScope:** `$watchCollection` should call listener with old value
([78057a94](https://github.com/angular/angular.js/commit/78057a945ef84cbb05f9417fe884cb8c28e67b44),
[#2621](https://github.com/angular/angular.js/issues/2621), [#5661](https://github.com/angular/angular.js/issues/5661), [#5688](https://github.com/angular/angular.js/issues/5688), [#6736](https://github.com/angular/angular.js/issues/6736))
- **angular.bootstrap:** allow angular to load only once
([748a6c8d](https://github.com/angular/angular.js/commit/748a6c8d9d8d61c3ee18eec462abe8ff245d6a98),
[#5863](https://github.com/angular/angular.js/issues/5863), [#5587](https://github.com/angular/angular.js/issues/5587))
- **jqLite:** `inheritedData()` now traverses Shadow DOM boundaries via the `host` property of `DocumentFragment`
([8a96f317](https://github.com/angular/angular.js/commit/8a96f317e594a5096d4fa56ceae4c685eec8ac8b),
[#6637](https://github.com/angular/angular.js/issues/6637))
- **ngCookie:** convert non-string values to string
([36528310](https://github.com/angular/angular.js/commit/3652831084c3788f786046b907a7361d2e89c520),
[#6151](https://github.com/angular/angular.js/issues/6151), [#6220](https://github.com/angular/angular.js/issues/6220))
- **ngTouch:** update workaround for Webkit quirk
([bc42950b](https://github.com/angular/angular.js/commit/bc42950b514b60f319812eeb87aae2915e394237),
[#6302](https://github.com/angular/angular.js/issues/6302))
- **orderBy:** support string predicates containing non-ident characters
([37bc5ef4](https://github.com/angular/angular.js/commit/37bc5ef4d87f19da47d3ab454c43d1e532c4f924),
[#6143](https://github.com/angular/angular.js/issues/6143), [#6144](https://github.com/angular/angular.js/issues/6144))
- **select:** avoid checking option element's `selected` property in render
([f40f54c6](https://github.com/angular/angular.js/commit/f40f54c6da4a5399fe18a89d068634bb491e9f1a),
[#2448](https://github.com/angular/angular.js/issues/2448), [#5994](https://github.com/angular/angular.js/issues/5994))
## Features
- **$compile:** add support for `$observer` deregistration
([299b220f](https://github.com/angular/angular.js/commit/299b220f5e05e1d4e26bfd58d0b2fd7329ca76b1),
[#5609](https://github.com/angular/angular.js/issues/5609))
- **ngMock.$httpBackend:** added support for function as URL matcher
([d6cfcace](https://github.com/angular/angular.js/commit/d6cfcacee101f2738e0a224a3377232ff85f78a4),
[#4580](https://github.com/angular/angular.js/issues/4580))
## Breaking Changes
- **$compile:** due to [299b220f](https://github.com/angular/angular.js/commit/299b220f5e05e1d4e26bfd58d0b2fd7329ca76b1),
calling `attr.$observe` no longer returns the observer function, but a
deregistration function instead. To migrate the code follow the example below:
Before:
directive('directiveName', function() {
return {
link: function(scope, elm, attr) {
var observer = attr.$observe('someAttr', function(value) {
console.log(value);
});
}
};
});
After:
directive('directiveName', function() {
return {
link: function(scope, elm, attr) {
var observer = function(value) {
console.log(value);
};
attr.$observe('someAttr', observer);
}
};
});
- **$httpBackend:** due to [6680b7b9](https://github.com/angular/angular.js/commit/6680b7b97c0326a80bdccaf0a35031e4af641e0e), the JSONP behavior for erroneous and empty responses changed:
Previously, a JSONP response was regarded as erroneous if it was empty. Now Angular is listening to the
correct events to detect errors, i.e. even empty responses can be successful.
<a name="v1.2.15"></a>
# v1.2.15 beer-underestimating (2014-03-21)
@@ -1772,64 +1117,6 @@ After:
<a name="1.3.0-beta.2"></a>
# 1.3.0-beta.2 silent-ventriloquism (2014-03-14)
## Bug Fixes
- **$$rAF:** always fallback to a $timeout in case native rAF isn't supported
([7b5e0199](https://github.com/angular/angular.js/commit/7b5e019981f352add88be2984de68e553d1bfa93),
[#6654](https://github.com/angular/angular.js/issues/6654))
- **$http:** don't convert 0 status codes to 404 for non-file protocols
([56e73ea3](https://github.com/angular/angular.js/commit/56e73ea355c851fdfd574d6d2a9e2fcb75677945),
[#6074](https://github.com/angular/angular.js/issues/6074), [#6155](https://github.com/angular/angular.js/issues/6155))
- **ngAnimate:** setting classNameFilter disables animation inside ng-if
([129e2e02](https://github.com/angular/angular.js/commit/129e2e021ab1d773874428cd1fb329eae72797c4),
[#6539](https://github.com/angular/angular.js/issues/6539))
## Features
- whitelist blob urls for sanitization of data-bound image urls
([47ab8df4](https://github.com/angular/angular.js/commit/47ab8df455df1f1391b760e1fbcc5c21645512b8),
[#4623](https://github.com/angular/angular.js/issues/4623))
<a name="1.3.0-beta.1"></a>
# 1.3.0-beta.1 retractable-eyebrow (2014-03-07)
## Bug Fixes
- **$compile:** support templates with thead and tfoot root elements
([53ec5e13](https://github.com/angular/angular.js/commit/53ec5e13e5955830b6751019eef232bd2125c0b6),
[#6289](https://github.com/angular/angular.js/issues/6289))
- **style:** expressions in style tags
([0609453e](https://github.com/angular/angular.js/commit/0609453e1f9ae074f8d786df903096a6eadb6aa0),
[#2387](https://github.com/angular/angular.js/issues/2387), [#6492](https://github.com/angular/angular.js/issues/6492))
## Features
- **input:** support types date, time, datetime-local, month, week
([46bd6dc8](https://github.com/angular/angular.js/commit/46bd6dc88de252886d75426efc2ce8107a5134e9),
[#5864](https://github.com/angular/angular.js/issues/5864))
## Breaking Changes
- **build:** due to [eaa1d00b](https://github.com/angular/angular.js/commit/eaa1d00b24008f590b95ad099241b4003688cdda),
As communicated before, IE8 is no longer supported.
- **input:** types date, time, datetime-local, month, week now always
require a `Date` object as model ([46bd6dc8](https://github.com/angular/angular.js/commit/46bd6dc88de252886d75426efc2ce8107a5134e9),
[#5864](https://github.com/angular/angular.js/issues/5864))
For more info: http://blog.angularjs.org/2013/12/angularjs-13-new-release-approaches.html
<a name="1.2.14"></a>
# 1.2.14 feisty-cryokinesis (2014-03-01)
@@ -2107,30 +1394,26 @@ The animation mock module has been renamed from `mock.animate` to `ngAnimateMock
## Breaking Changes
- **$http:** due to [e1cfb195](https://github.com/angular/angular.js/commit/e1cfb1957feaf89408bccf48fae6f529e57a82fe),
it is now necessary to seperately specify default HTTP headers for PUT, POST and PATCH requests, as these no longer share a single object.
it is now necessary to separately specify default HTTP headers for PUT, POST and PATCH requests, as these no longer share a single object.
To migrate your code, follow the example below:
To migrate your code, follow the example below:
Before:
Before:
```
// Will apply to POST, PUT and PATCH methods
$httpProvider.defaults.headers.post = {
"X-MY-CSRF-HEADER": "..."
};
```
// Will apply to POST, PUT and PATCH methods
$httpProvider.defaults.headers.post = {
"X-MY-CSRF-HEADER": "..."
};
After:
After:
```
// POST, PUT and PATCH default headers must be specified seperately,
// as they do not share data.
$httpProvider.defaults.headers.post =
$httpProvider.defaults.headers.put =
$httpProviders.defaults.headers.patch = {
"X-MY-CSRF-HEADER": "..."
};
```
// POST, PUT and PATCH default headers must be specified separately,
// as they do not share data.
$httpProvider.defaults.headers.post =
$httpProvider.defaults.headers.put =
$httpProviders.defaults.headers.patch = {
"X-MY-CSRF-HEADER": "..."
};
<a name="1.2.8"></a>
# 1.2.8 interdimensional-cartography (2014-01-10)
+5 -7
View File
@@ -40,13 +40,12 @@ would like to implement a new feature then consider what kind of change it is:
[dev mailing list][angular-dev] or [IRC][irc] so that we can better coordinate our efforts, prevent
duplication of work, and help you to craft the change so that it is successfully accepted into the
project.
* **Small Changes** can be crafted and submitted to the [GitHub Repository][github] as a Pull Request.
* **Small Changes** can be crafted and submitted to [GitHub Repository][github] as a Pull Request.
## <a name="docs"></a> Want a Doc Fix?
If you want to help improve the docs, it's a good idea to let others know what you're working on to
minimize duplication of effort. Before starting, check out the issue queue for
[Milestone:Docs Only](https://github.com/angular/angular.js/issues?milestone=24&state=open).
If you want to help improve the docs, it's a good idea to let others know what you're working on to
minimize duplication of effort. Before starting, check out the issue queue for [Milestone:Docs Only](https://github.com/angular/angular.js/issues?milestone=24&state=open).
Comment on an issue to let others know what you're working on, or create a new issue if your work
doesn't fit within the scope of any of the existing doc fix projects.
@@ -85,7 +84,7 @@ Before you submit your pull request consider the following guidelines:
* Search [GitHub](https://github.com/angular/angular.js/pulls) for an open or closed Pull Request
that relates to your submission. You don't want to duplicate effort.
* Please sign our [Contributor License Agreement (CLA)](#cla) before sending pull
* Please sign our [Contributor License Agreement (CLA)](#signing-the-cla) before sending pull
requests. We cannot accept code without this.
* Make your changes in a new git branch
@@ -94,7 +93,7 @@ Before you submit your pull request consider the following guidelines:
```
* Create your patch, **including appropriate test cases**.
* Follow our [Coding Rules](#rules).
* Follow our [Coding Rules](#coding-rules).
* Run the full Angular test suite, as described in the [developer documentation][dev-doc],
and ensure that all tests pass.
* Commit your changes using a descriptive commit message that follows our
@@ -260,7 +259,6 @@ You can find out more detailed information about contributing in the
[contribute]: http://docs.angularjs.org/misc/contribute
[contributing]: http://docs.angularjs.org/misc/contribute
[corporate-cla]: http://code.google.com/legal/corporate-cla-v1.0.html
[dev-doc]: https://docs.angularjs.org/guide
[github]: https://github.com/angular/angular.js
[groups]: https://groups.google.com/forum/?fromgroups#!forum/angular
[individual-cla]: http://code.google.com/legal/individual-cla-v1.0.html
+2 -10
View File
@@ -127,9 +127,6 @@ module.exports = function(grunt) {
ngLocale: {
files: { src: 'src/ngLocale/**/*.js' },
},
ngMessages: {
files: { src: 'src/ngMessages/**/*.js' },
},
ngMock: {
files: { src: 'src/ngMock/**/*.js' },
},
@@ -161,7 +158,7 @@ module.exports = function(grunt) {
scenario: {
dest: 'build/angular-scenario.js',
src: [
'bower_components/jquery/dist/jquery.js',
'bower_components/jquery/jquery.js',
util.wrap([files['angularSrc'], files['angularScenario']], 'ngScenario/angular')
],
styles: {
@@ -198,10 +195,6 @@ module.exports = function(grunt) {
dest: 'build/angular-resource.js',
src: util.wrap(files['angularModules']['ngResource'], 'module')
},
messages: {
dest: 'build/angular-messages.js',
src: util.wrap(files['angularModules']['ngMessages'], 'module')
},
animate: {
dest: 'build/angular-animate.js',
src: util.wrap(files['angularModules']['ngAnimate'], 'module')
@@ -226,7 +219,6 @@ module.exports = function(grunt) {
animate: 'build/angular-animate.js',
cookies: 'build/angular-cookies.js',
loader: 'build/angular-loader.js',
messages: 'build/angular-messages.js',
touch: 'build/angular-touch.js',
resource: 'build/angular-resource.js',
route: 'build/angular-route.js',
@@ -239,7 +231,7 @@ module.exports = function(grunt) {
'src/**/*.js',
'test/**/*.js',
'!test/ngScenario/DescribeSpec.js',
'!src/ng/directive/attrs.js', // legitimate xit here
'!src/ng/directive/booleanAttrs.js', // legitimate xit here
'!src/ngScenario/**/*.js'
]
},
+3 -8
View File
@@ -46,7 +46,7 @@ var angularFiles = {
'src/ng/directive/directives.js',
'src/ng/directive/a.js',
'src/ng/directive/attrs.js',
'src/ng/directive/booleanAttrs.js',
'src/ng/directive/form.js',
'src/ng/directive/input.js',
'src/ng/directive/ngBind.js',
@@ -82,9 +82,6 @@ var angularFiles = {
'ngCookies': [
'src/ngCookies/cookies.js'
],
'ngMessages': [
'src/ngMessages/messages.js'
],
'ngResource': [
'src/ngResource/resource.js'
],
@@ -133,7 +130,6 @@ var angularFiles = {
'test/auto/*.js',
'test/ng/**/*.js',
'test/ngAnimate/*.js',
'test/ngMessages/*.js',
'test/ngCookies/*.js',
'test/ngResource/*.js',
'test/ngRoute/**/*.js',
@@ -143,7 +139,7 @@ var angularFiles = {
],
'karma': [
'bower_components/jquery/dist/jquery.js',
'bower_components/jquery/jquery.js',
'test/jquery_remove.js',
'@angularSrc',
'src/publishExternalApis.js',
@@ -177,7 +173,7 @@ var angularFiles = {
],
'karmaJquery': [
'bower_components/jquery/dist/jquery.js',
'bower_components/jquery/jquery.js',
'test/jquery_alias.js',
'@angularSrc',
'src/publishExternalApis.js',
@@ -195,7 +191,6 @@ var angularFiles = {
angularFiles['angularSrcModules'] = [].concat(
angularFiles['angularModules']['ngAnimate'],
angularFiles['angularModules']['ngMessages'],
angularFiles['angularModules']['ngCookies'],
angularFiles['angularModules']['ngResource'],
angularFiles['angularModules']['ngRoute'],
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "AngularJS",
"devDependencies": {
"jquery": "2.1.1",
"jquery": "1.10.2",
"lunr.js": "0.4.3",
"open-sans-fontface": "1.0.4",
"google-code-prettify": "1.0.1",
+3 -6
View File
@@ -1,4 +1,4 @@
#!/usr/bin/env node
#!/usr/local/bin/node
'use strict';
@@ -123,12 +123,9 @@ then(function (tags) {
value();
}).
then(function (tags) {
var master = tags.pop();
var stable = tags.pop();
return [
{ name: stable.replace(/\d+$/, 'x'), tag: stable },
{ name: 'master', tag: master}
{ name: 'v1.0.x', tag: tags[0] },
{ name: 'master', tag: tags[1] }
];
}).
then(allInSeries(function (branch) {
+12 -1
View File
@@ -2,10 +2,21 @@
[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak],
.ng-cloak, .x-ng-cloak,
.ng-hide:not(.ng-animate) {
.ng-hide {
display: none !important;
}
ng\:form {
display: block;
}
.ng-animate-block-transitions {
transition:0s all!important;
-webkit-transition:0s all!important;
}
/* show the element during a show/hide animation when the
* animation is ongoing, but the .ng-hide class is active */
.ng-hide-add-active, .ng-hide-remove {
display: block!important;
}
+1 -1
View File
@@ -215,7 +215,7 @@ directive.ngEmbedApp = ['$templateCache', '$browser', '$rootScope', '$location',
}
});
element.on('$destroy', function() {
element.bind('$destroy', function() {
deregisterEmbedRootScope();
embedRootScope.$destroy();
});
+4 -4
View File
@@ -274,13 +274,13 @@ var popoverElement = function() {
this.contentElement = angular.element(inner.childNodes[1]);
//stop the click on the tooltip
this.element.on('click', function(event) {
this.element.bind('click', function(event) {
event.preventDefault();
event.stopPropagation();
});
var self = this;
angular.element(document.body).on('click',function(event) {
angular.element(document.body).bind('click',function(event) {
if(self.visible()) self.hide();
});
},
@@ -359,7 +359,7 @@ directive.popover = ['popoverElement', function(popover) {
restrict: 'A',
priority : 500,
link: function(scope, element, attrs) {
element.on('click',function(event) {
element.bind('click',function(event) {
event.preventDefault();
event.stopPropagation();
if(popover.isSituatedAt(element) && popover.visible()) {
@@ -396,7 +396,7 @@ directive.foldout = ['$http', '$animate','$window', function($http, $animate, $w
if(/\/build\//.test($window.location.href)) {
url = '/build/docs' + url;
}
element.on('click',function() {
element.bind('click',function() {
scope.$apply(function() {
if(!container) {
if(loading) return;
+5 -5
View File
@@ -35,8 +35,8 @@ angular.module('ui.bootstrap.dropdown', [])
this.open = function( dropdownScope ) {
if ( !openScope ) {
$document.on('click', closeDropdown);
$document.on('keydown', escapeKeyBind);
$document.bind('click', closeDropdown);
$document.bind('keydown', escapeKeyBind);
}
if ( openScope && openScope !== dropdownScope ) {
@@ -49,8 +49,8 @@ angular.module('ui.bootstrap.dropdown', [])
this.close = function( dropdownScope ) {
if ( openScope === dropdownScope ) {
openScope = null;
$document.off('click', closeDropdown);
$document.off('keydown', escapeKeyBind);
$document.unbind('click', closeDropdown);
$document.unbind('keydown', escapeKeyBind);
}
};
@@ -124,7 +124,7 @@ angular.module('ui.bootstrap.dropdown', [])
return;
}
element.on('click', function(event) {
element.bind('click', function(event) {
event.preventDefault();
event.stopPropagation();
+1 -1
View File
@@ -22,7 +22,7 @@ angular.module('directives', [])
terminal: true,
compile: function(element) {
var linenums = element.hasClass('linenum');// || element.parent()[0].nodeName === 'PRE';
var match = /lang-(\S+)/.exec(element[0].className);
var match = /lang-(\S)+/.exec(element.className);
var lang = match && match[1];
var html = element.html();
element.html(window.prettyPrintOne(html, lang, linenums));
+2 -2
View File
@@ -131,7 +131,7 @@ angular.module('search', [])
return function(scope, element, attrs) {
var ESCAPE_KEY_KEYCODE = 27,
FORWARD_SLASH_KEYCODE = 191;
angular.element($document[0].body).on('keydown', function(event) {
angular.element($document[0].body).bind('keydown', function(event) {
var input = element[0];
if(event.keyCode == FORWARD_SLASH_KEYCODE && document.activeElement != input) {
event.stopPropagation();
@@ -140,7 +140,7 @@ angular.module('search', [])
}
});
element.on('keydown', function(event) {
element.bind('keydown', function(event) {
if(event.keyCode == ESCAPE_KEY_KEYCODE) {
event.stopPropagation();
event.preventDefault();
-38
View File
@@ -1,38 +0,0 @@
describe("code", function() {
var prettyPrintOne, oldPP;
var compile, scope;
var any = jasmine.any;
beforeEach(module('directives'));
beforeEach(inject(function($rootScope, $compile) {
// Provide stub for pretty print function
oldPP = window.prettyPrintOne;
prettyPrintOne = window.prettyPrintOne = jasmine.createSpy();
scope = $rootScope.$new();
compile = $compile;
}));
afterEach(function() {
window.prettyPrintOne = oldPP;
});
it('should pretty print innerHTML', function() {
compile('<code>var x;</code>')(scope);
expect(prettyPrintOne).toHaveBeenCalledWith('var x;', null, false);
});
it('should allow language declaration', function() {
compile('<code class="lang-javascript"></code>')(scope);
expect(prettyPrintOne).toHaveBeenCalledWith(any(String), 'javascript', false);
});
it('supports allow line numbers', function() {
compile('<code class="linenum"></code>')(scope);
expect(prettyPrintOne).toHaveBeenCalledWith(any(String), null, true);
});
});
@@ -1,54 +0,0 @@
@ngdoc error
@name $injector:strictdi
@fullName Explicit annotation required
@description
This error occurs when attempting to invoke a function or provider which
has not been explicitly annotated, while the application is running with
strict-di mode enabled.
For example:
```
angular.module("myApp", [])
// BadController cannot be invoked, because
// the dependencies to be injected are not
// explicitly listed.
.controller("BadController", function($scope, $http, $filter) {
// ...
});
```
To fix the error, explicitly annotate the function using either the inline
bracket notation, or with the $inject property:
```
function GoodController1($scope, $http, $filter) {
// ...
}
GoodController1.$inject = ["$scope", "$http", "$filter"];
angular.module("myApp", [])
// GoodController1 can be invoked because it
// had an $inject property, which is an array
// containing the dependency names to be
// injected.
.controller("GoodController1", GoodController1)
// GoodController2 can also be invoked, because
// the dependencies to inject are listed, in
// order, in the array, with the function to be
// invoked trailing on the end.
.controller("GoodController2", [
"$scope",
"$http",
"$filter",
function($scope, $http, $filter) {
// ...
}
]);
```
For more information about strict-di mode, see {@link ng.directive:ngApp ngApp}
and {@link api/angular.bootstrap angular.bootstrap}.
@@ -1,21 +0,0 @@
@ngdoc error
@name ngModel:constexpr
@fullName Non-Constant Expression
@description
Some attributes used in conjunction with ngModel (such as ngTrueValue or ngFalseValue) will only
accept constant expressions.
Examples using constant expressions include:
```
<input type="checkbox" ng-model="..." ng-true-value="'truthyValue'">
<input type="checkbox" ng-model="..." ng-false-value="0">
```
Examples of non-constant expressions include:
```
<input type="checkbox" ng-model="..." ng-true-value="someValue">
<input type="checkbox" ng-model="..." ng-false-value="{foo: someScopeValue}">
```
+14 -8
View File
@@ -808,21 +808,27 @@ then uses the information it obtains to compose hashbang URLs (such as
## Two-way binding to $location
Because `$location` uses getters/setters, you can use `ng-model-options="{ getterSetter: true }"`
to bind it to `ngModel`:
The Angular's compiler currently does not support two-way binding for methods (see [issue](https://github.com/angular/angular.js/issues/404)). If you should require two-way binding
to the $location object (using {@link input[text] ngModel} directive on an input
field), you will need to specify an extra model property (e.g. `locationPath`) with two {@link ng.$rootScope.Scope#$watch $watchers}
which push $location updates in both directions. For example:
<example module="locationExample">
<file name="index.html">
<div ng-controller="LocationController">
<input type="text" ng-model="locationPath" ng-model-options="{ getterSetter: true }" />
<input type="text" ng-model="locationPath" />
</div>
</file>
<file name="script.js">
angular.module('locationExample', [])
.controller('LocationController', ['$scope', '$location', function($scope, $location) {
$scope.locationPath = function (newLocation) {
return $location.path(newLocation);
};
.controller('LocationController', ['$scope', '$location', function ($scope, $location) {
$scope.$watch('locationPath', function(path) {
$location.path(path);
});
$scope.$watch(function() {
return $location.path();
}, function(path) {
$scope.locationPath = path;
});
}]);
</file>
</example>
+25 -13
View File
@@ -33,14 +33,23 @@ Below is a quick example of animations being enabled for `ngShow` and `ngHide`:
background:white;
}
.sample-show-hide {
.sample-show-hide.ng-hide-add, .sample-show-hide.ng-hide-remove {
-webkit-transition:all linear 0.5s;
-moz-transition:all linear 0.5s;
-o-transition:all linear 0.5s;
transition:all linear 0.5s;
display:block!important;
}
.sample-show-hide.ng-hide {
.sample-show-hide.ng-hide-add.ng-hide-add-active,
.sample-show-hide.ng-hide-remove {
opacity:0;
}
.sample-show-hide.ng-hide-add,
.sample-show-hide.ng-hide-remove.ng-hide-remove-active {
opacity:1;
}
</file>
</example>
@@ -242,15 +251,18 @@ Although the CSS is a little different then what we saw before, the idea is the
A handful of common AngularJS directives support and trigger animation hooks whenever any major event occurs during its life cycle.
The table below explains in detail which animation events are triggered
| Directive | Supported Animations |
|-------------------------------------------------------------------------------------|------------------------------------------|
| {@link ng.directive:ngRepeat#usage_animations ngRepeat} | enter, leave, and move |
| {@link ngRoute.directive:ngView#usage_animations ngView} | enter and leave |
| {@link ng.directive:ngInclude#usage_animations ngInclude} | enter and leave |
| {@link ng.directive:ngSwitch#usage_animations ngSwitch} | enter and leave |
| {@link ng.directive:ngIf#usage_animations ngIf} | enter and leave |
| {@link ng.directive:ngClass#usage_animations ngClass or &#123;&#123;class&#125;&#125;} | add and remove |
| {@link ng.directive:ngShow#usage_animations ngShow & ngHide} | add and remove (the ng-hide class value) |
-| Directive | Supported Animations |
-|-----------------------------------------------------------------|--------------------------------------------------------------------------|
-| {@link ng.directive:ngRepeat#usage_animations ngRepeat} | enter, leave and move |
-| {@link ngRoute.directive:ngView#usage_animations ngView} | enter and leave |
-| {@link ng.directive:ngInclude#usage_animations ngInclude} | enter and leave |
-| {@link ng.directive:ngSwitch#usage_animations ngSwitch} | enter and leave |
-| {@link ng.directive:ngIf#usage_animations ngIf} | enter and leave |
-| {@link ng.directive:ngClass#usage_animations ngClass} | add and remove |
-| {@link ng.directive:ngShow#usage_animations ngShow & ngHide} | add and remove (the ng-hide class value) |
-| {@link ng.directive:form#usage_animations form} | add and remove (dirty, pristine, valid, invalid & all other validations) |
-| {@link ng.directive:ngModel#usage_animations ngModel} | add and remove (dirty, pristine, valid, invalid & all other validations) |
For a full breakdown of the steps involved during each animation event, refer to the {@link ngAnimate.$animate API docs}.
@@ -261,8 +273,8 @@ making calls to it when needed.
```js
myModule.directive('my-directive', ['$animate', function($animate) {
return function(scope, element, attrs) {
element.on('click', function() {
return function(element, scope, attrs) {
element.bind('click', function() {
if(element.hasClass('clicked')) {
$animate.removeClass(element, 'clicked');
} else {
+5 -1
View File
@@ -38,7 +38,11 @@ initialization.
<html ng-app>
3. If you choose to use the old style directive syntax `ng:` then include xml-namespace in `html`
3. If you require IE7 support add `id="ng-app"`
<html ng-app id="ng-app">
4. If you choose to use the old style directive syntax `ng:` then include xml-namespace in `html`
to make IE happy. (This is here for historical reasons, and we no longer recommend use of
`ng:`.)
+2 -2
View File
@@ -105,8 +105,8 @@ Here is a directive which makes any element draggable. Notice the `draggable` at
}
function mouseup() {
$document.off('mousemove', mousemove);
$document.off('mouseup', mouseup);
$document.unbind('mousemove', mousemove);
$document.unbind('mouseup', mouseup);
}
};
});
+8 -8
View File
@@ -37,10 +37,10 @@ Let's start with input fields for quantity and cost whose values are multiplied
<div ng-app ng-init="qty=1;cost=2">
<b>Invoice:</b>
<div>
Quantity: <input type="number" min="0" ng-model="qty">
Quantity: <input type="number" ng-model="qty">
</div>
<div>
Costs: <input type="number" min="0" ng-model="cost">
Costs: <input type="number" ng-model="cost">
</div>
<div>
<b>Total:</b> {{qty * cost | currency}}
@@ -128,10 +128,10 @@ different currencies and also pay the invoice.
<div ng-app="invoice1" ng-controller="InvoiceController as invoice">
<b>Invoice:</b>
<div>
Quantity: <input type="number" min="0" ng-model="invoice.qty" required >
Quantity: <input type="number" ng-model="invoice.qty" required >
</div>
<div>
Costs: <input type="number" min="0" ng-model="invoice.cost" required >
Costs: <input type="number" ng-model="invoice.cost" required >
<select ng-model="invoice.inCurr">
<option ng-repeat="c in invoice.currencies">{{c}}</option>
</select>
@@ -228,10 +228,10 @@ Let's refactor our example and move the currency conversion into a service in an
<div ng-app="invoice2" ng-controller="InvoiceController as invoice">
<b>Invoice:</b>
<div>
Quantity: <input type="number" min="0" ng-model="invoice.qty" required >
Quantity: <input type="number" ng-model="invoice.qty" required >
</div>
<div>
Costs: <input type="number" min="0" ng-model="invoice.cost" required >
Costs: <input type="number" ng-model="invoice.cost" required >
<select ng-model="invoice.inCurr">
<option ng-repeat="c in invoice.currencies">{{c}}</option>
</select>
@@ -356,10 +356,10 @@ The following example shows how this is done with Angular:
<div ng-app="invoice3" ng-controller="InvoiceController as invoice">
<b>Invoice:</b>
<div>
Quantity: <input type="number" min="0" ng-model="invoice.qty" required >
Quantity: <input type="number" ng-model="invoice.qty" required >
</div>
<div>
Costs: <input type="number" min="0" ng-model="invoice.cost" required >
Costs: <input type="number" ng-model="invoice.cost" required >
<select ng-model="invoice.inCurr">
<option ng-repeat="c in invoice.currencies">{{c}}</option>
</select>
+1 -1
View File
@@ -158,7 +158,7 @@ Things to notice in the example above:
- The `ng-controller` directive is used to (implicitly) create a scope for our template, and the
scope is augmented (managed) by the `SpicyController` Controller.
- `SpicyController` is just a plain JavaScript function. As an (optional) naming convention the name
starts with capital letter and ends with "Controller".
starts with capital letter and ends with "Controller" or "Controller".
- Assigning a property to `$scope` creates or updates the model.
- Controller methods can be created through direct assignment to scope (see the `chiliSpicy` method)
- The Controller methods and properties are available in the template (for the `<div>` element and
+2 -2
View File
@@ -797,8 +797,8 @@ element?
}
function mouseup() {
$document.off('mousemove', mousemove);
$document.off('mouseup', mouseup);
$document.unbind('mousemove', mousemove);
$document.unbind('mouseup', mouseup);
}
};
}]);
+2 -2
View File
@@ -12,7 +12,7 @@ is now in maintenance mode.
</div>
As applications grow in size and complexity, it becomes unrealistic to rely on manual testing to
verify the correctness of new features, catch bugs and notice regressions. Unit tests
verify the correctness of new features, catch bugs and notice regressions. End to end tests
are the first line of defense for catching bugs, but sometimes issues come up with integration
between components which can't be captured in a unit test. End to end tests are made to find
these problems.
@@ -27,7 +27,7 @@ Protractor is a [Node.js](http://nodejs.org) program, and runs end to end tests
written in JavaScript and run with node. Protractor uses [WebDriver](https://code.google.com/p/selenium/wiki/GettingStarted)
to control browsers and simulate user actions.
For more information on Protractor, view [getting started](https://github.com/angular/protractor/blob/master/docs/overview.md)
For more information on Protractor, view [getting started](https://github.com/angular/protractor/blob/master/docs/getting-started.md)
or the [api docs](https://github.com/angular/protractor/blob/master/docs/api.md).
Protractor uses [Jasmine](http://jasmine.github.io/1.3/introduction.html) for its test syntax.
-119
View File
@@ -202,122 +202,3 @@ expose a `$event` object within the scope of that expression.
Note in the example above how we can pass in `$event` to `clickMe`, but how it does not show up
in `{{$event}}`. This is because `$event` is outside the scope of that binding.
## One-time binding
An expression that starts with `::` is considered a one-time expression. One-time expressions
will stop recalculating once they are stable, which happens after the first digest if the expression
result is a non-undefined value (see value stabilization algorithm below).
<example module="oneTimeBidingExampleApp">
<file name="index.html">
<div ng-controller="EventController">
<button ng-click="clickMe($event)">Click Me</button>
<p id="one-time-binding-example">One time binding: {{::name}}</p>
<p id="normal-binding-example">Normal binding: {{name}}</p>
</div>
</file>
<file name="script.js">
angular.module('oneTimeBidingExampleApp', []).
controller('EventController', ['$scope', function($scope) {
var counter = 0;
var names = ['Igor', 'Misko', 'Chirayu', 'Lucas'];
/*
* expose the event object to the scope
*/
$scope.clickMe = function(clickEvent) {
$scope.name = names[counter % names.length];
counter++;
};
}]);
</file>
<file name="protractor.js" type="protractor">
it('should freeze binding after its value has stabilized', function() {
var oneTimeBiding = element(by.id('one-time-binding-example'));
var normalBinding = element(by.id('normal-binding-example'));
expect(oneTimeBiding.getText()).toEqual('One time binding:');
expect(normalBinding.getText()).toEqual('Normal binding:');
element(by.buttonText('Click Me')).click();
expect(oneTimeBiding.getText()).toEqual('One time binding: Igor');
expect(normalBinding.getText()).toEqual('Normal binding: Igor');
element(by.buttonText('Click Me')).click();
expect(oneTimeBiding.getText()).toEqual('One time binding: Igor');
expect(normalBinding.getText()).toEqual('Normal binding: Misko');
element(by.buttonText('Click Me')).click();
element(by.buttonText('Click Me')).click();
expect(oneTimeBiding.getText()).toEqual('One time binding: Igor');
expect(normalBinding.getText()).toEqual('Normal binding: Lucas');
});
</file>
</example>
### Why this feature
The main purpose of one-time binding expression is to provide a way to create a binding
that gets deregistered and frees up resources once the binding is stabilized.
Reducing the number of expressions being watched makes the digest loop faster and allows more
information to be displayed at the same time.
### Value stabilization algorithm
One-time binding expressions will retain the value of the expression at the end of the
digest cycle as long as that value is not undefined. If the value of the expression is set
within the digest loop and later, within the same digest loop, it is set to undefined,
then the expression is not fulfilled and will remain watched.
1. Given an expression that starts with `::` when a digest loop is entered and expression
is dirty-checked store the value as V
2. If V is not undefined mark the result of the expression as stable and schedule a task
to deregister the watch for this expression when we exit the digest loop
3. Process the digest loop as normal
4. When digest loop is done and all the values have settled process the queue of watch
deregistration tasks. For each watch to be deregistered check if it still evaluates
to value that is not `undefined`. If that's the case, deregister the watch. Otherwise
keep dirty-checking the watch in the future digest loops by following the same
algorithm starting from step 1
### How to benefit from one-time binding
When interpolating text or attributes. If the expression, once set, will not change
then it is a candidate for one-time expression.
```html
<div name="attr: {{::color}}">text: {{::name}}</div>
```
When using a directive with bidirectional binding and the parameters will not change
```js
someModule.directive('someDirective', function() {
return {
scope: {
name: '=',
color: '@'
},
template: '{{name}}: {{color}}'
};
});
```
```html
<div some-directive name=“::myName” color=“My color is {{::myColor}}”></div>
```
When using a directive that takes an expression
```html
<ul>
<li ng-repeat="item in ::items">{{item.name}};</li>
</ul>
```
-80
View File
@@ -63,8 +63,6 @@ To allow styling of form as well as controls, `ngModel` adds these CSS classes:
- `ng-invalid`
- `ng-pristine`
- `ng-dirty`
- `ng-touched`
- `ng-untouched`
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.
@@ -186,84 +184,6 @@ This allows us to extend the above example with these features:
# Custom triggers
By default, any change to the content will trigger a model update and form validation. You can
override this behavior using the {@link ng.directive:ngModelOptions ngModelOptions} directive to
bind only to specified list of events. I.e. `ng-model-options="{ updateOn: 'blur' }"` will update
and validate only after the control loses focus. You can set several events using a space delimited
list. I.e. `ng-model-options="{ updateOn: 'mousedown blur' }"`
If you want to keep the default behavior and just add new events that may trigger the model update
and validation, add "default" as one of the specified events.
I.e. `ng-model-options="{ updateOn: 'default blur' }"`
The following example shows how to override immediate updates. Changes on the inputs within the form will update the model
only when the control loses focus (blur event).
<example module="customTriggerExample">
<file name="index.html">
<div ng-controller="ExampleController">
<form>
Name:
<input type="text" ng-model="user.name" ng-model-options="{ updateOn: 'blur' }" /><br />
Other data:
<input type="text" ng-model="user.data" /><br />
</form>
<pre>username = "{{user.name}}"</pre>
</div>
</file>
<file name="script.js">
angular.module('customTriggerExample', [])
.controller('ExampleController', ['$scope', function($scope) {
$scope.user = {};
}]);
</file>
</example>
# Non-immediate (debounced) model updates
You can delay the model update/validation by using the `debounce` key with the
{@link ng.directive:ngModelOptions ngModelOptions} directive. This delay will also apply to
parsers, validators and model flags like `$dirty` or `$pristine`.
I.e. `ng-model-options="{ debounce: 500 }"` will wait for half a second since
the last content change before triggering the model update and form validation.
If custom triggers are used, custom debouncing timeouts can be set for each event using an object
in `debounce`. This can be useful to force immediate updates on some specific circumstances
(like blur events).
I.e. `ng-model-options="{ updateOn: 'default blur', debounce: { default: 500, blur: 0 } }"`
If those attributes are added to an element, they will be applied to all the child elements and controls that inherit from it unless they are
overridden.
This example shows how to debounce model changes. Model will be updated only 250 milliseconds after last change.
<example module="debounceExample">
<file name="index.html">
<div ng-controller="ExampleController">
<form>
Name:
<input type="text" ng-model="user.name" ng-model-options="{ debounce: 250 }" /><br />
</form>
<pre>username = "{{user.name}}"</pre>
</div>
</file>
<file name="script.js">
angular.module('debounceExample', [])
.controller('ExampleController', ['$scope', function($scope) {
$scope.user = {};
}]);
</file>
</example>
# Custom Validation
Angular provides basic implementation for most common html5 {@link ng.directive:input input}
+1 -1
View File
@@ -81,7 +81,7 @@ This is a short list of libraries with specific support and documentation for wo
### General
* **Javascript minification: **[Background](http://thegreenpizza.github.io/2013/05/25/building-minification-safe-angular.js-applications/), [ng-annotate automation tool](https://github.com/olov/ng-annotate)
* **Javascript minification: **[Background](http://thegreenpizza.github.io/2013/05/25/building-minification-safe-angular.js-applications/), [ngmin automation tool](http://www.thinkster.io/pick/XlWneEZCqY/angularjs-ngmin)
* **Analytics and Logging:** [Angularyitcs (Google Analytics)](http://ngmodules.org/modules/angularytics), [Angulartics (Analytics)](https://github.com/luisfarzati/angulartics), [Logging Client-Side Errors](http://www.bennadel.com/blog/2542-Logging-Client-Side-Errors-With-AngularJS-And-Stacktrace-js.htm)
* **SEO:** [By hand](http://www.yearofmoo.com/2012/11/angularjs-and-seo.html), [prerender.io](http://prerender.io/), [Brombone](http://www.brombone.com/), [SEO.js](http://getseojs.com/), [SEO4Ajax](http://www.seo4ajax.com/)
+9 -383
View File
@@ -1,391 +1,17 @@
@ngdoc overview
@name Migrating from Previous Versions
@name Migrating from 1.0 to 1.2
@description
Minor version releases in AngularJS introduce several breaking changes that may require changes to your
application's source code; for instance from 1.0 to 1.2 and from 1.2 to 1.3.
Although we try to avoid breaking changes, there are some cases where it is unavoidable.
* AngularJS has undergone thorough security reviews to make applications safer by default,
which drives many of these changes.
* Several new features, especially animations, would not be possible without a few changes.
* Finally, some outstanding bugs were best fixed by changing an existing API.
# Migrating from 1.2 to 1.3
- **$parse:**
- due to [77ada4c8](https://github.com/angular/angular.js/commit/77ada4c82d6b8fc6d977c26f3cdb48c2f5fbe5a5),
You can no longer invoke .bind, .call or .apply on a function in angular expressions.
This is to disallow changing the behaviour of existing functions
in an unforseen fashion.
- due to [6081f207](https://github.com/angular/angular.js/commit/6081f20769e64a800ee8075c168412b21f026d99),
The (deprecated) __proto__ propery does not work inside angular expressions
anymore.
- due to [48fa3aad](https://github.com/angular/angular.js/commit/48fa3aadd546036c7e69f71046f659ab1de244c6),
This prevents the use of __{define,lookup}{Getter,Setter}__ inside angular
expressions. If you really need them for some reason, please wrap/bind them to make them
less dangerous, then make them available through the scope object.
- due to [528be29d](https://github.com/angular/angular.js/commit/528be29d1662122a34e204dd607e1c0bd9c16bbc),
This prevents the use of `Object` inside angular expressions.
If you need Object.keys, make it accessible in the scope.
- **Angular.copy:** due to [b59b04f9](https://github.com/angular/angular.js/commit/b59b04f98a0b59eead53f6a53391ce1bbcbe9b57),
This changes `angular.copy` so that it applies the prototype of the original
object to the copied object. Previously, `angular.copy` would copy properties
of the original object's prototype chain directly onto the copied object.
This means that if you iterate over only the copied object's `hasOwnProperty`
properties, it will no longer contain the properties from the prototype.
This is actually much more reasonable behaviour and it is unlikely that
applications are actually relying on this.
If this behaviour is relied upon, in an app, then one should simply iterate
over all the properties on the object (and its inherited properties) and
not filter them with `hasOwnProperty`.
**Be aware that this change also uses a feature that is not compatible with
IE8.** If you need this to work on IE8 then you would need to provide a polyfill
for `Object.create` and `Object.getPrototypeOf`.
- **core:** due to [bdfc9c02](https://github.com/angular/angular.js/commit/bdfc9c02d021e08babfbc966a007c71b4946d69d),
values 'f', '0', 'false', 'no', 'n', '[]' are no longer
treated as falsy. Only JavaScript falsy values are now treated as falsy by the
expression parser; there are six of them: false, null, undefined, NaN, 0 and "".
Closes #3969
Closes #4277
Closes #7960
- **$compile:** due to [2cde927e](https://github.com/angular/angular.js/commit/2cde927e58c8d1588569d94a797e43cdfbcedaf9),
Requesting isolate scope and any other scope on a single element is an error.
Before this change, the compiler let two directives request a child scope
and an isolate scope if the compiler applied them in the order of non-isolate
scope directive followed by isolate scope directive.
Now the compiler will error regardless of the order.
If you find that your code is now throwing a `$compile:multidir` error,
check that you do not have directives on the same element that are trying
to request both an isolate and a non-isolate scope and fix your code.
Closes #4402
Closes #4421
- **NgModel:** due to [1be9bb9d](https://github.com/angular/angular.js/commit/1be9bb9d3527e0758350c4f7417a4228d8571440),
If an expression is used on ng-pattern (such as `ng-pattern="exp"`) or on the
pattern attribute (something like on `pattern="{{ exp }}"`) and the expression
itself evaluates to a string then the validator will not parse the string as a
literal regular expression object (a value like `/abc/i`). Instead, the entire
string will be created as the regular expression to test against. This means
that any expression flags will not be placed on the RegExp object. To get around
this limitation, use a regular expression object as the value for the expression.
//before
$scope.exp = '/abc/i';
//after
$scope.exp = /abc/i;
- **Scope:** due to [8c6a8171](https://github.com/angular/angular.js/commit/8c6a8171f9bdaa5cdabc0cc3f7d3ce10af7b434d),
Scope#$id is now of time number rather than string. Since the
id is primarily being used for debugging purposes this change should not affect
anyone.
- **forEach:** due to [55991e33](https://github.com/angular/angular.js/commit/55991e33af6fece07ea347a059da061b76fc95f5),
forEach will iterate only over the initial number of items in
the array. So if items are added to the array during the iteration, these won't
be iterated over during the initial forEach call.
This change also makes our forEach behave more like Array#forEach.
- **jqLite:** due to [a196c8bc](https://github.com/angular/angular.js/commit/a196c8bca82a28c08896d31f1863cf4ecd11401c),
previously it was possible to set jqLite data on Text/Comment
nodes, but now that is allowed only on Element and Document nodes just like in
jQuery. We don't expect that app code actually depends on this accidental feature.
- **$resource:** due to [d3c50c84](https://github.com/angular/angular.js/commit/d3c50c845671f0f8bcc3f7842df9e2fb1d1b1c40),
If you expected `$resource` to strip these types of properties before,
you will have to manually do this yourself now.
- **angular.toJson:** due to [c054288c](https://github.com/angular/angular.js/commit/c054288c9722875e3595e6e6162193e0fb67a251),
If you expected `toJson` to strip these types of properties before,
you will have to manually do this yourself now.
- **$compile:** due to [eec6394a](https://github.com/angular/angular.js/commit/eec6394a342fb92fba5270eee11c83f1d895e9fb), The `replace` flag for defining directives that
replace the element that they are on will be removed in the next major angular version.
This feature has difficult semantics (e.g. how attributes are merged) and leads to more
problems compared to what it solves. Also, with Web Components it is normal to have
custom elements in the DOM.
- **$parse:** due to [fa6e411d](https://github.com/angular/angular.js/commit/fa6e411da26824a5bae55f37ce7dbb859653276d),
promise unwrapping has been removed. It has been deprecated since 1.2.0-rc.3.
It can no longer be turned on.
Two methods have been removed:
* `$parseProvider.unwrapPromises`
* `$parseProvider.logPromiseWarnings`
- **Scope:** due to [82f45aee](https://github.com/angular/angular.js/commit/82f45aee5bd84d1cc53fb2e8f645d2263cdaacbc),
[#7445](https://github.com/angular/angular.js/issues/7445),
[#7523](https://github.com/angular/angular.js/issues/7523)
`$broadcast` and `$emit` will now reset the `currentScope` property of the event to
null once the event finished propagating. If any code depends on asynchronously accessing their
`currentScope` property, it should be migrated to use `targetScope` instead. All of these cases
should be considered programming bugs.
- **jqLite:** due to [d71dbb1a](https://github.com/angular/angular.js/commit/d71dbb1ae50f174680533492ce4c7db3ff74df00),
the jQuery `detach()` method does not trigger the `$destroy` event.
If you want to destroy Angular data attached to the element, use `remove()`.
- **$http:** due to [ad4336f9](https://github.com/angular/angular.js/commit/ad4336f9359a073e272930f8f9bcd36587a8648f),
Previously, it was possible to register a response interceptor like so:
```js
// register the interceptor as a service
$provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {
return function(promise) {
return promise.then(function(response) {
// do something on success
return response;
}, function(response) {
// do something on error
if (canRecover(response)) {
return responseOrNewPromise
}
return $q.reject(response);
});
}
});
$httpProvider.responseInterceptors.push('myHttpInterceptor');
```
Now, one must use the newer API introduced in v1.1.4 (4ae46814), like so:
```js
$provide.factory('myHttpInterceptor', function($q) {
return {
response: function(response) {
// do something on success
return response;
},
responseError: function(response) {
// do something on error
if (canRecover(response)) {
return responseOrNewPromise
}
return $q.reject(response);
}
};
});
$httpProvider.interceptors.push('myHttpInterceptor');
```
More details on the new interceptors API (which has been around as of v1.1.4) can be found at
https://docs.angularjs.org/api/ng/service/$http#interceptors
- **injector:** due to [c0b4e2db](https://github.com/angular/angular.js/commit/c0b4e2db9cbc8bc3164cedc4646145d3ab72536e),
Previously, config blocks would be able to control behaviour of provider registration, due to being
invoked prior to provider registration. Now, provider registration always occurs prior to configuration
for a given module, and therefore config blocks are not able to have any control over a providers
registration.
**Example**:
Previously, the following:
```js
angular.module('foo', [])
.provider('$rootProvider', function() {
this.$get = function() { ... }
})
.config(function($rootProvider) {
$rootProvider.dependentMode = "B";
})
.provider('$dependentProvider', function($rootProvider) {
if ($rootProvider.dependentMode === "A") {
this.$get = function() {
// Special mode!
}
} else {
this.$get = function() {
// something else
}
}
});
```
would have "worked", meaning behaviour of the config block between the registration of "$rootProvider"
and "$dependentProvider" would have actually accomplished something and changed the behaviour of the
app. This is no longer possible within a single module.
- **ngModelOptions:** due to [adfc322b](https://github.com/angular/angular.js/commit/adfc322b04a58158fb9697e5b99aab9ca63c80bb),
This commit changes the API on `NgModelController`, both semantically and
in terms of adding and renaming methods.
* `$setViewValue(value)` -
This method still changes the `$viewValue` but does not immediately commit this
change through to the `$modelValue` as it did previously.
Now the value is committed only when a trigger specified in an associated
`ngModelOptions` directive occurs. If `ngModelOptions` also has a `debounce` delay
specified for the trigger then the change will also be debounced before being
committed.
In most cases this should not have a significant impact on how `NgModelController`
is used: If `updateOn` includes `default` then `$setViewValue` will trigger
a (potentially debounced) commit immediately.
* `$cancelUpdate()` - is renamed to `$rollbackViewValue()` and has the same meaning,
which is to revert the current `$viewValue` back to the `$lastCommittedViewValue`,
to cancel any pending debounced updates and to re-render the input.
To migrate code that used `$cancelUpdate()` follow the example below:
Before:
```js
$scope.resetWithCancel = function (e) {
if (e.keyCode == 27) {
$scope.myForm.myInput1.$cancelUpdate();
$scope.myValue = '';
}
};
```
After:
```js
$scope.resetWithCancel = function (e) {
if (e.keyCode == 27) {
$scope.myForm.myInput1.$rollbackViewValue();
$scope.myValue = '';
}
}
```
- **$interpolate:** due to [88c2193c](https://github.com/angular/angular.js/commit/88c2193c71954b9e7e7e4bdf636a2b168d36300d),
the function returned by `$interpolate`
no longer has a `.parts` array set on it.
Instead it has two arrays:
* `.expressions`, an array of the expressions in the
interpolated text. The expressions are parsed with
`$parse`, with an extra layer converting them to strings
when computed
* `.separators`, an array of strings representing the
separations between interpolations in the text.
This array is **always** 1 item longer than the
`.expressions` array for easy merging with it
- **$animate:** due to [1cb8584e](https://github.com/angular/angular.js/commit/1cb8584e8490ecdb1b410a8846c4478c6c2c0e53),
`$animate` will no longer default the after parameter to the last element of the parent
container. Instead, when after is not specified, the new element will be inserted as the
first child of the parent container.
To update existing code, change all instances of `$animate.enter()` or `$animate.move()` from:
`$animate.enter(element, parent);`
to:
`$animate.enter(element, parent, angular.element(parent[0].lastChild));`
- **$animate:** due to [1bebe36a](https://github.com/angular/angular.js/commit/1bebe36aa938890d61188762ed618b1b5e193634),
Any class-based animation code that makes use of transitions
and uses the setup CSS classes (such as class-add and class-remove) must now
provide a empty transition value to ensure that its styling is applied right
away. In other words if your animation code is expecting any styling to be
applied that is defined in the setup class then it will not be applied
"instantly" unless a `transition:0s none` value is present in the styling
for that CSS class. This situation is only the case if a transition is already
present on the base CSS class once the animation kicks off.
Before:
.animated.my-class-add {
opacity:0;
transition:0.5s linear all;
}
.animated.my-class-add.my-class-add-active {
opacity:1;
}
After:
.animated.my-class-add {
transition:0s linear all;
opacity:0;
}
.animated.my-class-add.my-class-add-active {
transition:0.5s linear all;
opacity:1;
}
Please view the documentation for ngAnimate for more info.
- **$compile:** due to [299b220f](https://github.com/angular/angular.js/commit/299b220f5e05e1d4e26bfd58d0b2fd7329ca76b1),
calling `attr.$observe` no longer returns the observer function, but a
deregistration function instead. To migrate the code follow the example below:
Before:
directive('directiveName', function() {
return {
link: function(scope, elm, attr) {
var observer = attr.$observe('someAttr', function(value) {
console.log(value);
});
}
};
});
After:
directive('directiveName', function() {
return {
link: function(scope, elm, attr) {
var observer = function(value) {
console.log(value);
};
attr.$observe('someAttr', observer);
}
};
});
- **$httpBackend:** due to [6680b7b9](https://github.com/angular/angular.js/commit/6680b7b97c0326a80bdccaf0a35031e4af641e0e), the JSONP behavior for erroneous and empty responses changed:
Previously, a JSONP response was regarded as erroneous if it was empty. Now Angular is listening to the
correct events to detect errors, i.e. even empty responses can be successful.
- **build:** due to [eaa1d00b](https://github.com/angular/angular.js/commit/eaa1d00b24008f590b95ad099241b4003688cdda),
As communicated before, IE8 is no longer supported.
- **input:** types date, time, datetime-local, month, week now always
require a `Date` object as model ([46bd6dc8](https://github.com/angular/angular.js/commit/46bd6dc88de252886d75426efc2ce8107a5134e9),
[#5864](https://github.com/angular/angular.js/issues/5864))
# Migrating from 1.0 to 1.2
AngularJS version 1.2 introduces several breaking changes that may require changes to your
application's source code.
Although we try to avoid breaking changes, there are some cases where it is unavoidable.
AngularJS 1.2 has undergone a thorough security review to make applications safer by default,
which has driven many of these changes. Several new features, especially animations, would not
be possible without a few changes. Finally, some outstanding bugs were best fixed by changing
an existing API.
<div class="alert alert-warning">
<p>**Note:** AngularJS versions 1.1.x are considered "experimental" with breaking changes between minor releases.
+2 -2
View File
@@ -135,8 +135,8 @@ code, your variable names will get renamed unless you use one of the annotation
</div>
<div class="alert alert-info">
If you use a tool like [ng-annotate](https://github.com/olov/ng-annotate) in your workflow you can
use implicit dependency notation within your codebase and let **ng-annotate** automatically convert such
If you use a tool like [ngmin](https://github.com/btford/ngmin#ngmin) in your workflow you can
use implicit dependency notation within your codebase and let **ngmin** automatically convert such
injectable functions to the array notation prior to minifying.
</div>
+1 -1
View File
@@ -96,7 +96,7 @@ function MyClass() {
```
While no new dependency instance is created, it is fundamentally the same as `new` in
that no way exists to intercept the call to `global.xhr` for testing purposes, other than
that no way exists to intercept the call to `global.xhr` for testing purposes, other then
through monkey patching. The basic issue for testing is that a global variable needs to be mutated in
order to replace it with call to a mock method. For further explanation of why this is bad see: [Brittle Global
State & Singletons](http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/)
+3 -4
View File
@@ -51,7 +51,7 @@ Yes. See instructions in {@link downloading}.
### What browsers does Angular work with?
We run our extensive test suite against the following browsers: Safari, Chrome, Firefox, Opera,
IE9 and mobile browsers (Android, Chrome Mobile, iOS Safari). See {@link guide/ie Internet
IE8, IE9 and mobile browsers (Android, Chrome Mobile, iOS Safari). See {@link guide/ie Internet
Explorer Compatibility} for more details in supporting legacy IE browsers.
@@ -75,15 +75,14 @@ The size of the file is < 36KB compressed and minified.
Yes, you can use widgets from the [Closure Library](https://developers.google.com/closure/library/)
in Angular.
### Does Angular use the jQuery library?
Yes, Angular can use [jQuery](http://jquery.com/) if it's present in your app when the
application is being bootstrapped. If jQuery is not present in your script path, Angular falls back
to its own implementation of the subset of jQuery that we call {@link angular.element jQLite}.
Angular 1.3 only supports jQuery 2.1 or above. jQuery 1.7 and newer might work correctly with Angular
but we don't guarantee that.
Due to a change to use `on()`/`off()` rather than `bind()`/`unbind()`, Angular 1.2 only operates with
jQuery 1.7.1 or above. However, Angular does not currently support jQuery 2.x or above.
### What is testability like in Angular?
-5
View File
@@ -195,11 +195,6 @@ You can now browse to the application at:
http://localhost:8000/app/index.html
```
<div class="alert alert-info">
To serve the web app on a different ip address or port, edit the "start" script within package.json.
You can `-a` to set the address and `-p` to set the port.
</div>
### Running Unit Tests
We use unit tests to ensure that the JavaScript code in our application is operating correctly.
+1 -1
View File
@@ -67,7 +67,7 @@ __`app/index.html`:__
<html ng-app>
The `ng-app` attribute represents an Angular directive named `ngApp` (Angular uses
`spinal-case` for its custom attributes and `camelCase` for the corresponding directives
`name-with-dashes` for its custom attributes and `camelCase` for the corresponding directives
which implement them).
This directive is used to flag the html element that Angular should consider to be the root element
of our application.
+1 -1
View File
@@ -252,7 +252,7 @@ Our application routes are defined as follows:
controller.
* `when('/phones/:phoneId')`: The phone details view will be shown when the URL hash fragment
matches '/phones/:phoneId', where `:phoneId` is a variable part of the URL. To construct the phone
matches '/phone/:phoneId', where `:phoneId` is a variable part of the URL. To construct the phone
details view, Angular will use the `phone-detail.html` template and the `PhoneDetailCtrl`
controller.
+1 -1
View File
@@ -39,7 +39,7 @@ __`app/js/app.js`:__
```js
...
angular.module('phonecatApp', ['ngRoute','phonecatControllers','phonecatFilters']);
angular.module('phonecatApp', ['ngRoute','phonecatControllers','phonecatFilters']).
...
```
+1 -2
View File
@@ -104,8 +104,7 @@ __`app/index.html`.__
```
<div class="alert alert-error">
**Important:** Be sure to use jQuery version 2.1 or newer when using Angular 1.3; jQuery 1.x is
not officially supported.
**Important:** Be sure to use jQuery version `1.10.x`. AngularJS does not yet support jQuery `2.x`.
Be sure to load jQuery before all AngularJS scripts, otherwise AngularJS won't detect jQuery and
animations will not work as expected.
</div>
+30 -42
View File
@@ -33,8 +33,6 @@
goog.provide('goog.i18n.currency');
goog.provide('goog.i18n.currency.CurrencyInfo');
goog.provide('goog.i18n.currency.CurrencyInfoTier2');
/**
@@ -48,7 +46,7 @@ goog.i18n.currency.PRECISION_MASK_ = 0x07;
* Whether the currency sign should be positioned after the number.
* @private
*/
goog.i18n.currency.POSITION_FLAG_ = 0x10;
goog.i18n.currency.POSITION_FLAG_ = 0x08;
/**
@@ -58,13 +56,6 @@ goog.i18n.currency.POSITION_FLAG_ = 0x10;
goog.i18n.currency.SPACE_FLAG_ = 0x20;
/**
* Whether tier2 was enabled already by calling addTier2Support().
* @private
*/
goog.i18n.currency.tier2Enabled_ = false;
/**
* This function will add tier2 currency support. Be default, only tier1
* (most popular currencies) are supported. If an application really needs
@@ -72,13 +63,9 @@ goog.i18n.currency.tier2Enabled_ = false;
* before any other functions in this namespace.
*/
goog.i18n.currency.addTier2Support = function() {
// Protection from executing this these again and again.
if (!goog.i18n.currency.tier2Enabled_) {
for (var key in goog.i18n.currency.CurrencyInfoTier2) {
goog.i18n.currency.CurrencyInfo[key] =
goog.i18n.currency.CurrencyInfoTier2[key];
}
goog.i18n.currency.tier2Enabled_ = true;
for (var key in goog.i18n.currency.CurrencyInfoTier2) {
goog.i18n.currency.CurrencyInfo[key] =
goog.i18n.currency.CurrencyInfoTier2[key];
}
};
@@ -257,7 +244,7 @@ goog.i18n.currency.adjustPrecision = function(pattern, currencyCode) {
* the currency sign should be positioned after the number. Valid values are 0
* (before the number) or 16 (after the number). The space flag indicates
* whether a space should be inserted between the currency sign and number.
* Valid values are 0 (no space) and 32 (space).
* Valid values are 0 (no space) and 24 (space).
*
* The number in the array is calculated by adding together the mask and flag
* values. For example:
@@ -265,67 +252,52 @@ goog.i18n.currency.adjustPrecision = function(pattern, currencyCode) {
* 0: no precision (0), currency sign first (0), no space (0)
* 2: two decimals precision (2), currency sign first (0), no space (0)
* 18: two decimals precision (2), currency sign last (16), no space (0)
* 50: two decimals precision (2), currency sign last (16), space (32)
* 42: two decimals precision (2), currency sign last (16), space (24)
*
* @type {!Object.<!Array>}
*/
goog.i18n.currency.CurrencyInfo = {
'AED': [2, 'dh', '\u062f.\u0625.', 'DH'],
'ALL': [0, 'Lek', 'Lek'],
'AUD': [2, '$', 'AU$'],
'BDT': [2, '\u09F3', 'Tk'],
'BGN': [2, 'lev', 'lev'],
'BRL': [2, 'R$', 'R$'],
'CAD': [2, '$', 'C$'],
'CDF': [2, 'FrCD', 'CDF'],
'CHF': [2, 'CHF', 'CHF'],
'CLP': [0, '$', 'CL$'],
'CNY': [2, '¥', 'RMB¥'],
'COP': [0, '$', 'COL$'],
'CRC': [0, '\u20a1', 'CR\u20a1'],
'CZK': [50, 'K\u010d', 'K\u010d'],
'CZK': [2, 'K\u010d', 'K\u010d'],
'DKK': [18, 'kr', 'kr'],
'DOP': [2, '$', 'RD$'],
'EGP': [2, '£', 'LE'],
'ETB': [2, 'Birr', 'Birr'],
'EUR': [2, '€', '€'],
'EUR': [18, '', ''],
'GBP': [2, '£', 'GB£'],
'HKD': [2, '$', 'HK$'],
'HRK': [2, 'kn', 'kn'],
'HUF': [0, 'Ft', 'Ft'],
'IDR': [0, 'Rp', 'Rp'],
'ILS': [2, '\u20AA', 'IL\u20AA'],
'INR': [2, '\u20B9', 'Rs'],
'IRR': [0, 'Rial', 'IRR'],
'ISK': [0, 'kr', 'kr'],
'JMD': [2, '$', 'JA$'],
'JPY': [0, '¥', 'JP¥'],
'KRW': [0, '\u20A9', 'KR₩'],
'LKR': [2, 'Rs', 'SLRs'],
'LTL': [2, 'Lt', 'Lt'],
'LVL': [2, 'Ls', 'Ls'],
'MNT': [0, '\u20AE', 'MN₮'],
'MXN': [2, '$', 'Mex$'],
'MYR': [2, 'RM', 'RM'],
'NOK': [50, 'kr', 'NOkr'],
'NOK': [18, 'kr', 'NOkr'],
'PAB': [2, 'B/.', 'B/.'],
'PEN': [2, 'S/.', 'S/.'],
'PHP': [2, '\u20B1', 'Php'],
'PKR': [0, 'Rs', 'PKRs.'],
'PLN': [50, 'z\u0142', 'z\u0142'],
'RON': [2, 'RON', 'RON'],
'RSD': [0, 'din', 'RSD'],
'RUB': [50, 'руб.', 'руб.'],
'RUB': [42, 'руб.', 'руб.'],
'SAR': [2, 'Rial', 'Rial'],
'SEK': [2, 'kr', 'kr'],
'SGD': [2, '$', 'S$'],
'THB': [2, '\u0e3f', 'THB'],
'TRY': [2, 'TL', 'YTL'],
'TWD': [2, 'NT$', 'NT$'],
'TZS': [0, 'TSh', 'TSh'],
'UAH': [2, '\u20B4', 'UAH'],
'USD': [2, '$', 'US$'],
'UYU': [2, '$', '$U'],
'UYU': [2, '$', 'UY$'],
'VND': [0, '\u20AB', 'VN\u20AB'],
'YER': [0, 'Rial', 'Rial'],
'ZAR': [2, 'R', 'ZAR']
@@ -337,14 +309,16 @@ goog.i18n.currency.CurrencyInfo = {
* @type {!Object.<!Array>}
*/
goog.i18n.currency.CurrencyInfoTier2 = {
'AFN': [48, 'Af.', 'AFN'],
'AFN': [16, 'Af.', 'AFN'],
'ALL': [0, 'Lek', 'Lek'],
'AMD': [0, 'Dram', 'dram'],
'AOA': [2, 'Kz', 'Kz'],
'ARS': [2, '$', 'AR$'],
'AWG': [2, 'Afl.', 'Afl.'],
'AZN': [2, 'man.', 'man.'],
'BAM': [2, 'KM', 'KM'],
'BAM': [18, 'KM', 'KM'],
'BBD': [2, '$', 'Bds$'],
'BGN': [2, 'lev', 'lev'],
'BHD': [3, 'din', 'din'],
'BIF': [0, 'FBu', 'FBu'],
'BMD': [2, '$', 'BD$'],
@@ -355,12 +329,14 @@ goog.i18n.currency.CurrencyInfoTier2 = {
'BWP': [2, 'P', 'pula'],
'BYR': [0, 'BYR', 'BYR'],
'BZD': [2, '$', 'BZ$'],
'CDF': [2, 'FrCD', 'CDF'],
'CUC': [1, '$', 'CUC$'],
'CUP': [2, '$', 'CU$'],
'CVE': [2, 'CVE', 'Esc'],
'DJF': [0, 'Fdj', 'Fdj'],
'DZD': [2, 'din', 'din'],
'ERN': [2, 'Nfk', 'Nfk'],
'ETB': [2, 'Birr', 'Birr'],
'FJD': [2, '$', 'FJ$'],
'FKP': [2, '£', 'FK£'],
'GEL': [2, 'GEL', 'GEL'],
@@ -371,8 +347,12 @@ goog.i18n.currency.CurrencyInfoTier2 = {
'GTQ': [2, 'Q', 'GTQ'],
'GYD': [0, '$', 'GY$'],
'HNL': [2, 'L', 'HNL'],
'HRK': [2, 'kn', 'kn'],
'HTG': [2, 'HTG', 'HTG'],
'HUF': [0, 'Ft', 'Ft'],
'IDR': [0, 'Rp', 'Rp'],
'IQD': [0, 'din', 'IQD'],
'IRR': [0, 'Rial', 'IRR'],
'JOD': [3, 'din', 'JOD'],
'KES': [2, 'Ksh', 'Ksh'],
'KGS': [2, 'KGS', 'KGS'],
@@ -386,6 +366,8 @@ goog.i18n.currency.CurrencyInfoTier2 = {
'LBP': [0, 'L£', 'LBP'],
'LRD': [2, '$', 'L$'],
'LSL': [2, 'LSL', 'LSL'],
'LTL': [2, 'Lt', 'Lt'],
'LVL': [2, 'Ls', 'Ls'],
'LYD': [3, 'din', 'LD'],
'MAD': [2, 'dh', 'MAD'],
'MDL': [2, 'MDL', 'MDL'],
@@ -404,8 +386,11 @@ goog.i18n.currency.CurrencyInfoTier2 = {
'NZD': [2, '$', 'NZ$'],
'OMR': [3, 'Rial', 'OMR'],
'PGK': [2, 'PGK', 'PGK'],
'PLN': [2, 'z\u0142', 'z\u0142'],
'PYG': [0, 'Gs', 'PYG'],
'QAR': [2, 'Rial', 'QR'],
'RON': [2, 'RON', 'RON'],
'RSD': [0, 'din', 'RSD'],
'RWF': [0, 'RF', 'RF'],
'SBD': [2, '$', 'SI$'],
'SCR': [2, 'SCR', 'SCR'],
@@ -415,13 +400,16 @@ goog.i18n.currency.CurrencyInfoTier2 = {
'SOS': [0, 'SOS', 'SOS'],
'SRD': [2, '$', 'SR$'],
'STD': [0, 'Db', 'Db'],
'SYP': [0, '£', 'SY£'],
'SYP': [16, '£', 'SY£'],
'SZL': [2, 'SZL', 'SZL'],
'TJS': [2, 'Som', 'TJS'],
'TND': [3, 'din', 'DT'],
'TOP': [2, 'T$', 'T$'],
'TTD': [2, '$', 'TT$'],
'TZS': [0, 'TSh', 'TSh'],
'UAH': [2, '\u20B4', 'UAH'],
'UGX': [0, 'UGX', 'UGX'],
'UYU': [1, '$', '$U'],
'UZS': [0, 'so\u02bcm', 'UZS'],
'VEF': [2, 'Bs', 'Bs'],
'VUV': [0, 'VUV', 'VUV'],
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -7,7 +7,7 @@ echo "#################################"
# Enable tracing and exit on first failure
set -xe
# This is the default set of browsers to use on the CI server unless overridden via env variable
# Define reasonable set of browsers in case we are running manually from commandline
if [[ -z "$BROWSERS" ]]
then
BROWSERS="Chrome,Firefox,Opera,/Users/jenkins/bin/safari.sh"
+15 -4
View File
@@ -9,7 +9,7 @@ module.exports = function(config, specificOptions) {
browsers: ['Chrome'],
browserDisconnectTimeout: 10000,
browserDisconnectTolerance: 2,
browserNoActivityTimeout: 30000,
browserNoActivityTimeout: 20000,
// SauceLabs config for local development.
@@ -17,7 +17,7 @@ module.exports = function(config, specificOptions) {
testName: specificOptions.testName || 'AngularJS',
startConnect: true,
options: {
'selenium-version': '2.41.0'
'selenium-version': '2.37.0'
}
},
@@ -48,6 +48,12 @@ module.exports = function(config, specificOptions) {
platform: 'OS X 10.9',
version: '7'
},
'SL_IE_8': {
base: 'SauceLabs',
browserName: 'internet explorer',
platform: 'Windows 7',
version: '8'
},
'SL_IE_9': {
base: 'SauceLabs',
browserName: 'internet explorer',
@@ -85,6 +91,13 @@ module.exports = function(config, specificOptions) {
os: 'Windows',
os_version: '8'
},
'BS_IE_8': {
base: 'BrowserStack',
browser: 'ie',
browser_version: '8.0',
os: 'Windows',
os_version: '7'
},
'BS_IE_9': {
base: 'BrowserStack',
browser: 'ie',
@@ -115,7 +128,6 @@ module.exports = function(config, specificOptions) {
config.logLevel = config.LOG_DEBUG;
config.transports = ['websocket', 'xhr-polling'];
config.captureTimeout = 0; // rely on SL timeout
config.browserStack.build = buildLabel;
config.browserStack.startTunnel = false;
@@ -123,7 +135,6 @@ module.exports = function(config, specificOptions) {
config.sauceLabs.build = buildLabel;
config.sauceLabs.startConnect = false;
config.sauceLabs.tunnelIdentifier = process.env.TRAVIS_JOB_NUMBER;
config.sauceLabs.recordScreenshots = true;
// TODO(vojta): remove once SauceLabs supports websockets.
// This speeds up the capturing a bit, as browsers don't even try to use websocket.
+6 -6
View File
@@ -2837,13 +2837,10 @@
"version": "0.1.1"
},
"glob": {
"version": "3.2.11",
"version": "3.2.9",
"dependencies": {
"inherits": {
"version": "2.0.1"
},
"minimatch": {
"version": "0.3.0",
"version": "0.2.14",
"dependencies": {
"lru-cache": {
"version": "2.5.0"
@@ -2852,6 +2849,9 @@
"version": "1.0.0"
}
}
},
"inherits": {
"version": "2.0.1"
}
}
},
@@ -2865,7 +2865,7 @@
"version": "0.0.2"
},
"minimist": {
"version": "0.0.10"
"version": "0.0.8"
}
}
},
+2 -3
View File
@@ -1,6 +1,6 @@
{
"name": "angularjs",
"branchVersion": "1.3.*",
"branchVersion": "1.2.*",
"repository": {
"type": "git",
"url": "https://github.com/angular/angular.js.git"
@@ -53,8 +53,7 @@
"jshint-stylish": "~0.1.5",
"node-html-encoder": "0.0.2",
"sorted-object": "^1.0.0",
"qq": "^0.3.5",
"benchmark": "1.x.x"
"qq": "^0.3.5"
},
"licenses": [
{
-121
View File
@@ -1,121 +0,0 @@
var app = angular.module('perf', ['ngBench'])
.directive('noopDir', function() {
return {
compile: function($element, $attrs) {
return function($scope, $element) {
return 1;
}
}
};
})
app.directive('nativeClick', ['$parse', function($parse) {
return {
compile: function($element, $attrs) {
var expr = $parse($attrs.tstEvent);
return function($scope, $element) {
$element[0].addEventListener('click', function() {
console.log('clicked');
}, false);
}
}
};
}])
.directive('dlgtClick', function() {
return {
compile: function($element, $attrs) {
var evt = $attrs.dlgtClick;
// We don't setup the global event listeners as the costs are small and one time only...
}
};
})
.controller('MainCtrl', ['$compile', '$rootScope', '$templateCache',
function($compile, $rootScope, $templateCache) {
// TODO: Make ngRepeatCount configurable via the UI!
var self = this;
this.ngRepeatCount = 20;
this.manualRepeatCount = 5;
this.benchmarks = [{
title: 'ng-click',
factory: function() {
return createBenchmark({
directive: 'ng-click="a()"'
});
},
active: true
},{
title: 'ng-click without jqLite',
factory: function() {
return createBenchmark({
directive: 'native-click="a()"'
});
},
active: true
},{
title: 'baseline: ng-show',
factory: function() {
return createBenchmark({
directive: 'ng-show="true"'
});
},
active: true
},{
title: 'baseline: text interpolation',
factory: function() {
return createBenchmark({
text: '{{row}}'
});
},
active: true
},{
title: 'delegate event directive (only compile)',
factory: function() {
return createBenchmark({
directive: 'dlgt-click="a()"'
});
},
active: true
},{
title: 'baseline: noop directive (compile and link)',
factory: function() {
return createBenchmark({
directive: 'noop-dir'
});
},
active: true
},{
title: 'baseline: no directive',
factory: function() {
return createBenchmark({});
},
active: true
}];
function createBenchmark(options) {
options.directive = options.directive || '';
options.text = options.text || '';
var templateHtml = '<div><span ng-repeat="row in rows">';
for (var i=0; i<self.manualRepeatCount; i++) {
templateHtml += '<span '+options.directive+'>'+options.text+'</span>';
}
templateHtml += '</span></div>';
var compiledTemplate = $compile(templateHtml);
var rows = [];
for (var i=0; i<self.ngRepeatCount; i++) {
rows.push('row'+i);
}
return function(container) {
var scope = $rootScope.$new();
try {
scope.rows = rows;
compiledTemplate(scope, function(clone) {
container.appendChild(clone[0]);
});
scope.$digest();
} finally {
scope.$destroy();
}
}
}
}])
-69
View File
@@ -1,69 +0,0 @@
<!DOCTYPE html>
<html ng-app="perf" ng-controller="MainCtrl as ctrl">
<head>
<meta charset="utf-8" />
<title>Event delegation</title>
<script src="../../../build/angular.js"></script>
<script src="../../../node_modules/benchmark/benchmark.js"></script>
<script src="ng_benchmark.js"></script>
<script src="app.js"></script>
</head>
<body>
<h1>
Benchmark: impact of event delegation
</h1>
How to run:
<ul>
<li>For most stable results, run this in Chrome with the following command line option:
<pre>--js-flags="--expose-gc"</pre>
</li>
</ul>
How to read the results:
<ul>
<li>The benchmark measures how long it takes to instantiate a given number of directives</li>
<li>ngClick is compared against ngShow and text interpolation as baseline. The results show
how expensive ngClick is compared to other very simple directives that touch the DOM.
</li>
<li>To measure the impact of jqLite.on vs element.addEventListener there is also a benchmark
that as a modified version of ngClick that uses element.addEventListener.
</li>
<li>The delegate event directive is compared against a noop directive with a compile and link function and the case with no directives.
The result shows how expensive it is to add a link function to a directive, as the delegate event directive has none.
</li>
</ul>
Results as of 7/31/2014:
<ul>
<li>ngClick is very close to ngShow and text interpolation, especially when looking at a version of ngClick that does not use jqLite.on but element.addEventListener instead.</li>
<li>A delegate event directive that has no link function has the same speed as a directive with link function. I.e. ngClick is slower compared to the delegate event directive only because ngClick touches
the DOM for every element</li>
<li>A delegate event directive could be about 2x faster than ngClick. However, the overall performance
benefit depends on how many (and which) other directives are used on the same element
and what other things are part of the measures use case.
E.g. rows of a table with ngRepeat that use ngClick will probably also contain text interpolation.
</li>
</ul>
Benchmark Options:
<p>
<label>
Number of ngRepeats:
<input type="number" ng-model="ctrl.ngRepeatCount">
</label>
<br>
<label>
Number of manual repeats inside the ngRepeat:
<input type="number" ng-model="ctrl.manualRepeatCount">
</label>
</p>
<div ng-bench="ctrl.benchmarks"></div>
</body>
</html>
@@ -1,27 +0,0 @@
Benchmarks:
<table>
<thead>
<td>Name</td>
<td>State</td>
<td>Result</td>
</thead>
<tbody>
<tr ng-repeat="bench in benchmarks">
<td>
<label><input type="checkbox" ng-model="bench.active">{{bench.title}}
</label>
</td>
<td>{{bench.state}}</td>
<td>{{bench.lastResult}}</td>
</tr>
<tbody>
</table>
<div>
<button ng-click="ngBenchCtrl.toggleAll()">Toggle all</button>
<button ng-click="ngBenchCtrl.run()">Run</button>
<button ng-click="ngBenchCtrl.runOnce()">Debug once</button>
</div>
Benchmark work area:
<div class="work" style="height:20px; overflow: auto"></div>
-104
View File
@@ -1,104 +0,0 @@
(function() {
var ngBenchmarkTemplateUrl = getCurrentScript().replace('.js', '.html');
angular.module('ngBench', []).directive('ngBench', function() {
return {
scope: {
'benchmarks': '=ngBench'
},
templateUrl: ngBenchmarkTemplateUrl,
controllerAs: 'ngBenchCtrl',
controller: ['$scope', '$element', NgBenchController]
};
});
function NgBenchController($scope, $element) {
var container = $element[0].querySelector('.work');
this.toggleAll = function() {
var newState = !$scope.benchmarks[0].active;
$scope.benchmarks.forEach(function(benchmark) {
benchmark.active = newState;
});
};
this.run = function() {
var suite = new Benchmark.Suite();
$scope.benchmarks.forEach(function(benchmark) {
var options = {
'model': benchmark,
'onStart': function() {
benchmark.state = 'running';
$scope.$digest();
},
'setup': function() {
window.gc && window.gc();
},
'onComplete': function(event) {
benchmark.state = '';
if (this.error) {
benchmark.lastResult = this.error.stack;
} else {
benchmark.lastResult = benchResultToString(this);
}
$scope.$digest();
},
delegate: createBenchmarkFn(benchmark.factory)
};
benchmark.state = '';
if (benchmark.active) {
benchmark.state = 'waiting';
suite.add(benchmark.title, 'this.delegate()', options);
}
});
suite.run({'async': true});
};
this.runOnce = function() {
window.setTimeout(function() {
$scope.benchmarks.forEach(function(benchmark) {
benchmark.state = '';
if (benchmark.active) {
try {
createBenchmarkFn(benchmark.factory)();
benchmark.lastResult = '';
} catch (e) {
benchmark.lastResult = e.message;
}
}
});
$scope.$digest();
});
};
function createBenchmarkFn(factory) {
var instance = factory();
return function() {
container.innerHTML = '';
instance(container);
}
}
}
// See benchmark.js, toStringBench,
// but without showing the name
function benchResultToString(bench) {
var me = bench,
hz = me.hz,
stats = me.stats,
size = stats.sample.length;
return Benchmark.formatNumber(hz.toFixed(hz < 100 ? 2 : 0)) + ' ops/sec +/-' +
stats.rme.toFixed(2) + '% (' + size + ' run' + (size == 1 ? '' : 's') + ' sampled)';
}
function getCurrentScript() {
var script = document.currentScript;
if (!script) {
var scripts = document.getElementsByTagName('script');
script = scripts[scripts.length - 1];
}
return script.src;
}
})();
-1
View File
@@ -26,7 +26,6 @@ function init {
angular-sanitize
angular-scenario
angular-touch
angular-messages
)
}
+2 -2
View File
@@ -7,8 +7,8 @@ export SAUCE_ACCESS_KEY=`echo $SAUCE_ACCESS_KEY | rev`
if [ $JOB = "unit" ]; then
grunt ci-checks
grunt test:promises-aplus
grunt test:unit --browsers SL_Chrome,SL_Safari,SL_Firefox,SL_IE_9,SL_IE_10,SL_IE_11 --reporters dots
grunt tests:docs --browsers SL_Chrome,SL_Safari,SL_Firefox,SL_IE_9,SL_IE_10,SL_IE_11 --reporters dots
grunt test:unit --browsers SL_Chrome,SL_Safari,SL_Firefox,SL_IE_8,SL_IE_9,SL_IE_10,SL_IE_11 --reporters dots
grunt tests:docs --browsers SL_Chrome,SL_Safari,SL_Firefox,SL_IE_8,SL_IE_9,SL_IE_10,SL_IE_11 --reporters dots
elif [ $JOB = "e2e" ]; then
export TARGET_SPECS="build/docs/ptore2e/**/*jqlite_test.js"
if [ $TEST_TARGET = "jquery" ]; then
+1 -6
View File
@@ -19,7 +19,6 @@
"nodeName_": false,
"uid": false,
"REGEX_STRING_REGEXP" : false,
"lowercase": false,
"uppercase": false,
"manualLowercase": false,
@@ -71,6 +70,7 @@
"toJsonReplacer": false,
"toJson": false,
"fromJson": false,
"toBoolean": false,
"startingTag": false,
"tryDecodeURIComponent": false,
"parseKeyValue": false,
@@ -88,9 +88,6 @@
"getBlockElements": false,
"VALIDITY_STATE_PROPERTY": false,
/* filters.js */
"getFirstThursdayOfYear": false,
/* AngularPublic.js */
"version": false,
"publishExternalAPI": false,
@@ -103,7 +100,6 @@
/* jqLite.js */
"BOOLEAN_ATTR": false,
"ALIASED_ATTR": false,
"jqNextId": false,
"camelCase": false,
"jqLitePatchJQueryRemove": false,
@@ -121,7 +117,6 @@
"jqLiteController": false,
"jqLiteInheritedData": false,
"getBooleanAttrName": false,
"getAliasedAttrName": false,
"createEventHandler": false,
"JQLitePrototype": false,
"addEventListenerFn": false,
+207 -287
View File
@@ -2,87 +2,87 @@
/* We need to tell jshint what variables are being exported */
/* global angular: true,
msie: true,
jqLite: true,
jQuery: true,
slice: true,
push: true,
toString: true,
ngMinErr: true,
angularModule: true,
nodeName_: true,
uid: true,
REGEX_STRING_REGEXP: true,
VALIDITY_STATE_PROPERTY: true,
msie: true,
jqLite: true,
jQuery: true,
slice: true,
push: true,
toString: true,
ngMinErr: true,
angularModule: true,
nodeName_: true,
uid: true,
VALIDITY_STATE_PROPERTY: true,
lowercase: true,
uppercase: true,
manualLowercase: true,
manualUppercase: true,
nodeName_: true,
isArrayLike: true,
forEach: true,
sortedKeys: true,
forEachSorted: true,
reverseParams: true,
nextUid: true,
setHashKey: true,
extend: true,
int: true,
inherit: true,
noop: true,
identity: true,
valueFn: true,
isUndefined: true,
isDefined: true,
isObject: true,
isString: true,
isNumber: true,
isDate: true,
isArray: true,
isFunction: true,
isRegExp: true,
isWindow: true,
isScope: true,
isFile: true,
isBlob: true,
isBoolean: true,
isPromiseLike: true,
trim: true,
isElement: true,
makeMap: true,
map: true,
size: true,
includes: true,
indexOf: true,
arrayRemove: true,
isLeafNode: true,
copy: true,
shallowCopy: true,
equals: true,
csp: true,
concat: true,
sliceArgs: true,
bind: true,
toJsonReplacer: true,
toJson: true,
fromJson: true,
startingTag: true,
tryDecodeURIComponent: true,
parseKeyValue: true,
toKeyValue: true,
encodeUriSegment: true,
encodeUriQuery: true,
angularInit: true,
bootstrap: true,
snake_case: true,
bindJQuery: true,
assertArg: true,
assertArgFn: true,
assertNotHasOwnProperty: true,
getter: true,
getBlockElements: true,
hasOwnProperty: true,
lowercase: true,
uppercase: true,
manualLowercase: true,
manualUppercase: true,
nodeName_: true,
isArrayLike: true,
forEach: true,
sortedKeys: true,
forEachSorted: true,
reverseParams: true,
nextUid: true,
setHashKey: true,
extend: true,
int: true,
inherit: true,
noop: true,
identity: true,
valueFn: true,
isUndefined: true,
isDefined: true,
isObject: true,
isString: true,
isNumber: true,
isDate: true,
isArray: true,
isFunction: true,
isRegExp: true,
isWindow: true,
isScope: true,
isFile: true,
isBlob: true,
isBoolean: true,
isPromiseLike: true,
trim: true,
isElement: true,
makeMap: true,
map: true,
size: true,
includes: true,
indexOf: true,
arrayRemove: true,
isLeafNode: true,
copy: true,
shallowCopy: true,
equals: true,
csp: true,
concat: true,
sliceArgs: true,
bind: true,
toJsonReplacer: true,
toJson: true,
fromJson: true,
toBoolean: true,
startingTag: true,
tryDecodeURIComponent: true,
parseKeyValue: true,
toKeyValue: true,
encodeUriSegment: true,
encodeUriQuery: true,
angularInit: true,
bootstrap: true,
snake_case: true,
bindJQuery: true,
assertArg: true,
assertArgFn: true,
assertNotHasOwnProperty: true,
getter: true,
getBlockElements: true,
hasOwnProperty: true,
*/
////////////////////////////////////
@@ -102,8 +102,6 @@
* <div doc-module-components="ng"></div>
*/
var REGEX_STRING_REGEXP = /^\/(.+)\/([a-z]*)$/;
// The name of a form control's ValidityState property.
// This is used so that it's possible for internal tests to create mock ValidityStates.
var VALIDITY_STATE_PROPERTY = 'validity';
@@ -170,7 +168,7 @@ var /** holds major version number for IE or NaN for real browsers */
angular = window.angular || (window.angular = {}),
angularModule,
nodeName_,
uid = 0;
uid = ['0', '0', '0'];
/**
* IE 11 changed the format of the UserAgent string.
@@ -232,9 +230,8 @@ function isArrayLike(obj) {
* @param {Object=} context Object to become context (`this`) for the iterator function.
* @returns {Object|Array} Reference to `obj`.
*/
function forEach(obj, iterator, context) {
var key, length;
var key;
if (obj) {
if (isFunction(obj)) {
for (key in obj) {
@@ -245,7 +242,7 @@ function forEach(obj, iterator, context) {
}
}
} else if (isArray(obj) || isArrayLike(obj)) {
for (key = 0, length = obj.length; key < length; key++) {
for (key = 0; key < obj.length; key++) {
iterator.call(context, obj[key], key);
}
} else if (obj.forEach && obj.forEach !== forEach) {
@@ -290,17 +287,33 @@ function reverseParams(iteratorFn) {
}
/**
* A consistent way of creating unique IDs in angular.
* A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric
* characters such as '012ABC'. The reason why we are not using simply a number counter is that
* the number string gets longer over time, and it can also overflow, where as the nextId
* will grow much slower, it is a string, and it will never overflow.
*
* Using simple numbers allows us to generate 28.6 million unique ids per second for 10 years before
* we hit number precision issues in JavaScript.
*
* Math.pow(2,53) / 60 / 60 / 24 / 365 / 10 = 28.6M
*
* @returns {number} an unique alpha-numeric string
* @returns {string} an unique alpha-numeric string
*/
function nextUid() {
return ++uid;
var index = uid.length;
var digit;
while(index) {
index--;
digit = uid[index].charCodeAt(0);
if (digit == 57 /*'9'*/) {
uid[index] = 'A';
return uid.join('');
}
if (digit == 90 /*'Z'*/) {
uid[index] = '0';
} else {
uid[index] = String.fromCharCode(digit + 1);
return uid.join('');
}
}
uid.unshift('0');
return uid.join('');
}
@@ -546,7 +559,7 @@ function isRegExp(value) {
* @returns {boolean} True if `obj` is a window obj.
*/
function isWindow(obj) {
return obj && obj.window === obj;
return obj && obj.document && obj.location && obj.alert && obj.setInterval;
}
@@ -623,14 +636,12 @@ function makeMap(str) {
if (msie < 9) {
nodeName_ = function(element) {
element = element.nodeName ? element : element[0];
return lowercase(
(element.scopeName && element.scopeName != 'HTML')
? element.scopeName + ':' + element.nodeName : element.nodeName
);
return (element.scopeName && element.scopeName != 'HTML')
? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;
};
} else {
nodeName_ = function(element) {
return lowercase(element.nodeName ? element.nodeName : element[0].nodeName);
return element.nodeName ? element.nodeName : element[0].nodeName;
};
}
@@ -693,10 +704,10 @@ function arrayRemove(array, value) {
function isLeafNode (node) {
if (node) {
switch (nodeName_(node)) {
case "option":
case "pre":
case "title":
switch (node.nodeName) {
case "OPTION":
case "PRE":
case "TITLE":
return true;
}
}
@@ -778,8 +789,7 @@ function copy(source, destination, stackSource, stackDest) {
destination = new RegExp(source.source, source.toString().match(/[^\/]*$/)[0]);
destination.lastIndex = source.lastIndex;
} else if (isObject(source)) {
var emptyObject = Object.create(Object.getPrototypeOf(source));
destination = copy(source, emptyObject, stackSource, stackDest);
destination = copy(source, {}, stackSource, stackDest);
}
}
} else {
@@ -814,14 +824,12 @@ function copy(source, destination, stackSource, stackDest) {
delete destination[key];
});
for ( var key in source) {
if(source.hasOwnProperty(key)) {
result = copy(source[key], null, stackSource, stackDest);
if (isObject(source[key])) {
stackSource.push(source[key]);
stackDest.push(result);
}
destination[key] = result;
result = copy(source[key], null, stackSource, stackDest);
if (isObject(source[key])) {
stackSource.push(source[key]);
stackDest.push(result);
}
destination[key] = result;
}
setHashKey(destination,h);
}
@@ -834,22 +842,17 @@ function copy(source, destination, stackSource, stackDest) {
* Creates a shallow copy of an object, an array or a primitive
*/
function shallowCopy(src, dst) {
var i = 0;
if (isArray(src)) {
dst = dst || [];
for (; i < src.length; i++) {
for ( var i = 0; i < src.length; i++) {
dst[i] = src[i];
}
} else if (isObject(src)) {
dst = dst || {};
var keys = Object.keys(src);
for (var l = keys.length; i < l; i++) {
var key = keys[i];
if (!(key.charAt(0) === '$' && key.charAt(1) === '$')) {
for (var key in src) {
if (hasOwnProperty.call(src, key) && !(key.charAt(0) === '$' && key.charAt(1) === '$')) {
dst[key] = src[key];
}
}
@@ -1001,7 +1004,7 @@ function bind(self, fn) {
function toJsonReplacer(key, value) {
var val = value;
if (typeof key === 'string' && key.charAt(0) === '$' && key.charAt(1) === '$') {
if (typeof key === 'string' && key.charAt(0) === '$') {
val = undefined;
} else if (isWindow(value)) {
val = '$WINDOW';
@@ -1022,7 +1025,7 @@ function toJsonReplacer(key, value) {
* @kind function
*
* @description
* Serializes input into a JSON-formatted string. Properties with leading $$ characters will be
* Serializes input into a JSON-formatted string. Properties with leading $ characters will be
* stripped since angular uses this notation internally.
*
* @param {Object|Array|Date|string|number} obj Input to be serialized into JSON.
@@ -1054,6 +1057,18 @@ function fromJson(json) {
}
function toBoolean(value) {
if (typeof value === 'function') {
value = true;
} else if (value && value.length !== 0) {
var v = lowercase("" + value);
value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]');
} else {
value = false;
}
return value;
}
/**
* @returns {string} Returns the string representation of the element.
*/
@@ -1176,23 +1191,9 @@ function encodeUriQuery(val, pctEncodeSpaces) {
replace(/%3A/gi, ':').
replace(/%24/g, '$').
replace(/%2C/gi, ',').
replace(/%3B/gi, ';').
replace(/%20/g, (pctEncodeSpaces ? '%20' : '+'));
}
var ngAttrPrefixes = ['ng-', 'data-ng-', 'ng:', 'x-ng-'];
function getNgAttribute(element, ngAttr) {
var attr, i, ii = ngAttrPrefixes.length;
element = jqLite(element);
for (i=0; i<ii; ++i) {
attr = ngAttrPrefixes[i] + ngAttr;
if (isString(attr = element.attr(attr))) {
return attr;
}
}
return null;
}
/**
* @ngdoc directive
@@ -1202,11 +1203,6 @@ function getNgAttribute(element, ngAttr) {
* @element ANY
* @param {angular.Module} ngApp an optional application
* {@link angular.module module} name to load.
* @param {boolean=} ngStrictDi if this attribute is present on the app element, the injector will be
* created in "strict-di" mode. This means that the application will fail to invoke functions which
* do not use explicit function annotation (and are thus unsuitable for minification), as described
* in {@link guide/di the Dependency Injection guide}, and useful debugging info will assist in
* tracking down the root of these bugs.
*
* @description
*
@@ -1244,109 +1240,48 @@ function getNgAttribute(element, ngAttr) {
</file>
</example>
*
* Using `ngStrictDi`, you would see something like this:
*
<example ng-app-included="true">
<file name="index.html">
<div ng-app="ngAppStrictDemo" ng-strict-di>
<div ng-controller="GoodController1">
I can add: {{a}} + {{b}} = {{ a+b }}
<p>This renders because the controller does not fail to
instantiate, by using explicit annotation style (see
script.js for details)
</p>
</div>
<div ng-controller="GoodController2">
Name: <input ng-model="name"><br />
Hello, {{name}}!
<p>This renders because the controller does not fail to
instantiate, by using explicit annotation style
(see script.js for details)
</p>
</div>
<div ng-controller="BadController">
I can add: {{a}} + {{b}} = {{ a+b }}
<p>The controller could not be instantiated, due to relying
on automatic function annotations (which are disabled in
strict mode). As such, the content of this section is not
interpolated, and there should be an error in your web console.
</p>
</div>
</div>
</file>
<file name="script.js">
angular.module('ngAppStrictDemo', [])
// BadController will fail to instantiate, due to relying on automatic function annotation,
// rather than an explicit annotation
.controller('BadController', function($scope) {
$scope.a = 1;
$scope.b = 2;
})
// Unlike BadController, GoodController1 and GoodController2 will not fail to be instantiated,
// due to using explicit annotations using the array style and $inject property, respectively.
.controller('GoodController1', ['$scope', function($scope) {
$scope.a = 1;
$scope.b = 2;
}])
.controller('GoodController2', GoodController2);
function GoodController2($scope) {
$scope.name = "World";
}
GoodController2.$inject = ['$scope'];
</file>
<file name="style.css">
div[ng-controller] {
margin-bottom: 1em;
-webkit-border-radius: 4px;
border-radius: 4px;
border: 1px solid;
padding: .5em;
}
div[ng-controller^=Good] {
border-color: #d6e9c6;
background-color: #dff0d8;
color: #3c763d;
}
div[ng-controller^=Bad] {
border-color: #ebccd1;
background-color: #f2dede;
color: #a94442;
margin-bottom: 0;
}
</file>
</example>
*/
function angularInit(element, bootstrap) {
var appElement,
var elements = [element],
appElement,
module,
config = {};
names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'],
NG_APP_CLASS_REGEXP = /\sng[:\-]app(:\s*([\w\d_]+);?)?\s/;
// The element `element` has priority over any other element
forEach(ngAttrPrefixes, function(prefix) {
var name = prefix + 'app';
function append(element) {
element && elements.push(element);
}
if (!appElement && element.hasAttribute && element.hasAttribute(name)) {
appElement = element;
module = element.getAttribute(name);
forEach(names, function(name) {
names[name] = true;
append(document.getElementById(name));
name = name.replace(':', '\\:');
if (element.querySelectorAll) {
forEach(element.querySelectorAll('.' + name), append);
forEach(element.querySelectorAll('.' + name + '\\:'), append);
forEach(element.querySelectorAll('[' + name + ']'), append);
}
});
forEach(ngAttrPrefixes, function(prefix) {
var name = prefix + 'app';
var candidate;
if (!appElement && (candidate = element.querySelector('[' + name.replace(':', '\\:') + ']'))) {
appElement = candidate;
module = candidate.getAttribute(name);
forEach(elements, function(element) {
if (!appElement) {
var className = ' ' + element.className + ' ';
var match = NG_APP_CLASS_REGEXP.exec(className);
if (match) {
appElement = element;
module = (match[2] || '').replace(/\s+/g, ',');
} else {
forEach(element.attributes, function(attr) {
if (!appElement && names[attr.name]) {
appElement = element;
module = attr.value;
}
});
}
}
});
if (appElement) {
config.strictDi = getNgAttribute(appElement, "strict-di") !== null;
bootstrap(appElement, module ? [module] : [], config);
bootstrap(appElement, module ? [module] : []);
}
}
@@ -1359,7 +1294,7 @@ function angularInit(element, bootstrap) {
*
* See: {@link guide/bootstrap Bootstrap}
*
* Note that Protractor based end-to-end tests cannot use this function to bootstrap manually.
* Note that ngScenario-based end-to-end tests cannot use this function to bootstrap manually.
* They must use {@link ng.directive:ngApp ngApp}.
*
* Angular will detect if it has been loaded into the browser more than once and only allow the
@@ -1367,45 +1302,44 @@ function angularInit(element, bootstrap) {
* each of the subsequent scripts. This prevents strange results in applications, where otherwise
* multiple instances of Angular try to work on the DOM.
*
* ```html
* <!doctype html>
* <html>
* <body>
* <div ng-controller="WelcomeController">
* {{greeting}}
* <example name="multi-bootstrap" module="multi-bootstrap">
* <file name="index.html">
* <script src="../../../angular.js"></script>
* <div ng-controller="BrokenTable">
* <table>
* <tr>
* <th ng-repeat="heading in headings">{{heading}}</th>
* </tr>
* <tr ng-repeat="filling in fillings">
* <td ng-repeat="fill in filling">{{fill}}</td>
* </tr>
* </table>
* </div>
* </file>
* <file name="controller.js">
* var app = angular.module('multi-bootstrap', [])
*
* <script src="angular.js"></script>
* <script>
* var app = angular.module('demo', [])
* .controller('WelcomeController', function($scope) {
* $scope.greeting = 'Welcome!';
* });
* angular.bootstrap(document, ['demo']);
* </script>
* </body>
* </html>
* ```
* .controller('BrokenTable', function($scope) {
* $scope.headings = ['One', 'Two', 'Three'];
* $scope.fillings = [[1, 2, 3], ['A', 'B', 'C'], [7, 8, 9]];
* });
* </file>
* <file name="protractor.js" type="protractor">
* it('should only insert one table cell for each item in $scope.fillings', function() {
* expect(element.all(by.css('td')).count())
* .toBe(9);
* });
* </file>
* </example>
*
* @param {DOMElement} element DOM element which is the root of angular application.
* @param {Array<String|Function|Array>=} modules an array of modules to load into the application.
* Each item in the array should be the name of a predefined module or a (DI annotated)
* function that will be invoked by the injector as a run block.
* See: {@link angular.module modules}
* @param {Object=} config an object for defining configuration options for the application. The
* following keys are supported:
*
* - `strictDi`: disable automatic function annotation for the application. This is meant to
* assist in finding bugs which break minified code.
*
* @returns {auto.$injector} Returns the newly created injector for this app.
*/
function bootstrap(element, modules, config) {
if (!isObject(config)) config = {};
var defaultConfig = {
strictDi: false
};
config = extend(defaultConfig, config);
function bootstrap(element, modules) {
var doBootstrap = function() {
element = jqLite(element);
@@ -1419,9 +1353,9 @@ function bootstrap(element, modules, config) {
$provide.value('$rootElement', element);
}]);
modules.unshift('ng');
var injector = createInjector(modules, config.strictDi);
injector.invoke(['$rootScope', '$rootElement', '$compile', '$injector',
function(scope, element, compile, injector) {
var injector = createInjector(modules);
injector.invoke(['$rootScope', '$rootElement', '$compile', '$injector', '$animate',
function(scope, element, compile, injector, animate) {
scope.$apply(function() {
element.data('$injector', injector);
compile(element)(scope);
@@ -1455,13 +1389,10 @@ function snake_case(name, separator) {
}
function bindJQuery() {
var originalCleanData;
// bind to jQuery if present;
jQuery = window.jQuery;
// Use jQuery if it exists with proper functionality, otherwise default to us.
// Angular 1.2+ requires jQuery 1.7+ for on()/off() support.
// Angular 1.3+ technically requires at least jQuery 2.1+ but it may work with older
// versions. It will not work for sure with jQuery <1.7, though.
// Angular 1.2+ requires jQuery 1.7.1+ for on()/off() support.
if (jQuery && jQuery.fn.on) {
jqLite = jQuery;
extend(jQuery.fn, {
@@ -1471,25 +1402,14 @@ function bindJQuery() {
injector: JQLitePrototype.injector,
inheritedData: JQLitePrototype.inheritedData
});
originalCleanData = jQuery.cleanData;
// Prevent double-proxying.
originalCleanData = originalCleanData.$$original || originalCleanData;
// All nodes removed from the DOM via various jQuery APIs like .remove()
// are passed through jQuery.cleanData. Monkey-patch this method to fire
// the $destroy event on all removed nodes.
jQuery.cleanData = function(elems) {
for (var i = 0, elem; (elem = elems[i]) != null; i++) {
jQuery(elem).triggerHandler('$destroy');
}
originalCleanData(elems);
};
jQuery.cleanData.$$original = originalCleanData;
// Method signature:
// jqLitePatchJQueryRemove(name, dispatchThis, filterElems, getterIfNoArguments)
jqLitePatchJQueryRemove('remove', true, true, false);
jqLitePatchJQueryRemove('empty', false, false, false);
jqLitePatchJQueryRemove('html', false, false, true);
} else {
jqLite = JQLite;
}
angular.element = jqLite;
}
+68 -84
View File
@@ -6,82 +6,74 @@
$LocaleProvider,
$CompileProvider,
htmlAnchorDirective,
inputDirective,
inputDirective,
formDirective,
scriptDirective,
selectDirective,
styleDirective,
optionDirective,
ngBindDirective,
ngBindHtmlDirective,
ngBindTemplateDirective,
ngClassDirective,
ngClassEvenDirective,
ngClassOddDirective,
ngCspDirective,
ngCloakDirective,
ngControllerDirective,
ngFormDirective,
ngHideDirective,
ngIfDirective,
ngIncludeDirective,
ngIncludeFillContentDirective,
ngInitDirective,
ngNonBindableDirective,
ngPluralizeDirective,
ngRepeatDirective,
ngShowDirective,
ngStyleDirective,
ngSwitchDirective,
ngSwitchWhenDirective,
ngSwitchDefaultDirective,
ngOptionsDirective,
ngTranscludeDirective,
ngModelDirective,
ngListDirective,
ngChangeDirective,
patternDirective,
patternDirective,
requiredDirective,
requiredDirective,
minlengthDirective,
minlengthDirective,
maxlengthDirective,
maxlengthDirective,
ngValueDirective,
ngModelOptionsDirective,
ngAttributeAliasDirectives,
ngEventDirectives,
htmlAnchorDirective,
inputDirective,
inputDirective,
formDirective,
scriptDirective,
selectDirective,
styleDirective,
optionDirective,
ngBindDirective,
ngBindHtmlDirective,
ngBindTemplateDirective,
ngClassDirective,
ngClassEvenDirective,
ngClassOddDirective,
ngCspDirective,
ngCloakDirective,
ngControllerDirective,
ngFormDirective,
ngHideDirective,
ngIfDirective,
ngIncludeDirective,
ngIncludeFillContentDirective,
ngInitDirective,
ngNonBindableDirective,
ngPluralizeDirective,
ngRepeatDirective,
ngShowDirective,
ngStyleDirective,
ngSwitchDirective,
ngSwitchWhenDirective,
ngSwitchDefaultDirective,
ngOptionsDirective,
ngTranscludeDirective,
ngModelDirective,
ngListDirective,
ngChangeDirective,
requiredDirective,
requiredDirective,
ngValueDirective,
ngAttributeAliasDirectives,
ngEventDirectives,
$AnchorScrollProvider,
$AnimateProvider,
$BrowserProvider,
$CacheFactoryProvider,
$ControllerProvider,
$DocumentProvider,
$ExceptionHandlerProvider,
$FilterProvider,
$InterpolateProvider,
$IntervalProvider,
$HttpProvider,
$HttpBackendProvider,
$LocationProvider,
$LogProvider,
$ParseProvider,
$RootScopeProvider,
$QProvider,
$$QProvider,
$$SanitizeUriProvider,
$SceProvider,
$SceDelegateProvider,
$SnifferProvider,
$TemplateCacheProvider,
$TimeoutProvider,
$$RAFProvider,
$$AsyncCallbackProvider,
$WindowProvider
$AnchorScrollProvider,
$AnimateProvider,
$BrowserProvider,
$CacheFactoryProvider,
$ControllerProvider,
$DocumentProvider,
$ExceptionHandlerProvider,
$FilterProvider,
$InterpolateProvider,
$IntervalProvider,
$HttpProvider,
$HttpBackendProvider,
$LocationProvider,
$LogProvider,
$ParseProvider,
$RootScopeProvider,
$QProvider,
$$SanitizeUriProvider,
$SceProvider,
$SceDelegateProvider,
$SnifferProvider,
$TemplateCacheProvider,
$TimeoutProvider,
$$RAFProvider,
$$AsyncCallbackProvider,
$WindowProvider
*/
@@ -188,16 +180,9 @@ function publishExternalAPI(angular){
ngModel: ngModelDirective,
ngList: ngListDirective,
ngChange: ngChangeDirective,
pattern: patternDirective,
ngPattern: patternDirective,
required: requiredDirective,
ngRequired: requiredDirective,
minlength: minlengthDirective,
ngMinlength: minlengthDirective,
maxlength: maxlengthDirective,
ngMaxlength: maxlengthDirective,
ngValue: ngValueDirective,
ngModelOptions: ngModelOptionsDirective
ngValue: ngValueDirective
}).
directive({
ngInclude: ngIncludeFillContentDirective
@@ -222,7 +207,6 @@ function publishExternalAPI(angular){
$parse: $ParseProvider,
$rootScope: $RootScopeProvider,
$q: $QProvider,
$$q: $$QProvider,
$sce: $SceProvider,
$sceDelegate: $SceDelegateProvider,
$sniffer: $SnifferProvider,
+21 -52
View File
@@ -23,7 +23,7 @@
*
* // use the injector to kick off your application
* // use the type inference to auto inject arguments, or use implicit injection
* $injector.invoke(function($rootScope, $compile, $document) {
* $injector.invoke(function($rootScope, $compile, $document){
* $compile($document)($rootScope);
* $rootScope.$digest();
* });
@@ -66,19 +66,7 @@ var FN_ARG_SPLIT = /,/;
var FN_ARG = /^\s*(_?)(\S+?)\1\s*$/;
var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
var $injectorMinErr = minErr('$injector');
function anonFn(fn) {
// For anonymous functions, showing at the very least the function signature can help in
// debugging.
var fnText = fn.toString().replace(STRIP_COMMENTS, ''),
args = fnText.match(FN_ARGS);
if (args) {
return 'function(' + (args[1] || '').replace(/[\s\r\n]+/, ' ') + ')';
}
return 'fn';
}
function annotate(fn, strictDi, name) {
function annotate(fn) {
var $inject,
fnText,
argDecl,
@@ -88,17 +76,10 @@ function annotate(fn, strictDi, name) {
if (!($inject = fn.$inject)) {
$inject = [];
if (fn.length) {
if (strictDi) {
if (!isString(name) || !name) {
name = fn.name || anonFn(fn);
}
throw $injectorMinErr('strictdi',
'{0} is not using explicit annotation and cannot be invoked in strict mode', name);
}
fnText = fn.toString().replace(STRIP_COMMENTS, '');
argDecl = fnText.match(FN_ARGS);
forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg) {
arg.replace(FN_ARG, function(all, underscore, name) {
forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){
arg.replace(FN_ARG, function(all, underscore, name){
$inject.push(name);
});
});
@@ -133,7 +114,7 @@ function annotate(fn, strictDi, name) {
* ```js
* var $injector = angular.injector();
* expect($injector.get('$injector')).toBe($injector);
* expect($injector.invoke(function($injector) {
* expect($injector.invoke(function($injector){
* return $injector;
* }).toBe($injector);
* ```
@@ -606,8 +587,7 @@ function annotate(fn, strictDi, name) {
*/
function createInjector(modulesToLoad, strictDi) {
strictDi = (strictDi === true);
function createInjector(modulesToLoad) {
var INSTANTIATING = {},
providerSuffix = 'Provider',
path = [],
@@ -625,13 +605,13 @@ function createInjector(modulesToLoad, strictDi) {
providerInjector = (providerCache.$injector =
createInternalInjector(providerCache, function() {
throw $injectorMinErr('unpr', "Unknown provider: {0}", path.join(' <- '));
}, strictDi)),
})),
instanceCache = {},
instanceInjector = (instanceCache.$injector =
createInternalInjector(instanceCache, function(servicename) {
var provider = providerInjector.get(servicename + providerSuffix);
return instanceInjector.invoke(provider.$get, provider, undefined, servicename);
}, strictDi));
return instanceInjector.invoke(provider.$get, provider);
}));
forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); });
@@ -693,27 +673,22 @@ function createInjector(modulesToLoad, strictDi) {
// Module Loading
////////////////////////////////////
function loadModules(modulesToLoad){
var runBlocks = [], moduleFn, invokeQueue;
var runBlocks = [], moduleFn, invokeQueue, i, ii;
forEach(modulesToLoad, function(module) {
if (loadedModules.get(module)) return;
loadedModules.put(module, true);
function runInvokeQueue(queue) {
var i, ii;
for(i = 0, ii = queue.length; i < ii; i++) {
var invokeArgs = queue[i],
provider = providerInjector.get(invokeArgs[0]);
provider[invokeArgs[1]].apply(provider, invokeArgs[2]);
}
}
try {
if (isString(module)) {
moduleFn = angularModule(module);
runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks);
runInvokeQueue(moduleFn._invokeQueue);
runInvokeQueue(moduleFn._configBlocks);
for(invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) {
var invokeArgs = invokeQueue[i],
provider = providerInjector.get(invokeArgs[0]);
provider[invokeArgs[1]].apply(provider, invokeArgs[2]);
}
} else if (isFunction(module)) {
runBlocks.push(providerInjector.invoke(module));
} else if (isArray(module)) {
@@ -769,14 +744,9 @@ function createInjector(modulesToLoad, strictDi) {
}
}
function invoke(fn, self, locals, serviceName) {
if (typeof locals === 'string') {
serviceName = locals;
locals = null;
}
function invoke(fn, self, locals){
var args = [],
$inject = annotate(fn, strictDi, serviceName),
$inject = annotate(fn),
length, i,
key;
@@ -801,7 +771,7 @@ function createInjector(modulesToLoad, strictDi) {
return fn.apply(self, args);
}
function instantiate(Type, locals, serviceName) {
function instantiate(Type, locals) {
var Constructor = function() {},
instance, returnedValue;
@@ -809,7 +779,7 @@ function createInjector(modulesToLoad, strictDi) {
// e.g. someModule.factory('greeter', ['$window', function(renamed$window) {}]);
Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype;
instance = new Constructor();
returnedValue = invoke(Type, instance, locals, serviceName);
returnedValue = invoke(Type, instance, locals);
return isObject(returnedValue) || isFunction(returnedValue) ? returnedValue : instance;
}
@@ -826,4 +796,3 @@ function createInjector(modulesToLoad, strictDi) {
}
}
createInjector.$$annotate = annotate;
+102 -97
View File
@@ -3,8 +3,7 @@
/* global JQLitePrototype: true,
addEventListenerFn: true,
removeEventListenerFn: true,
BOOLEAN_ATTR: true,
ALIASED_ATTR: true,
BOOLEAN_ATTR: true
*/
//////////////////////////////////
@@ -136,6 +135,49 @@ function camelCase(name) {
replace(MOZ_HACK_REGEXP, 'Moz$1');
}
/////////////////////////////////////////////
// jQuery mutation patch
//
// In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a
// $destroy event on all DOM nodes being removed.
//
/////////////////////////////////////////////
function jqLitePatchJQueryRemove(name, dispatchThis, filterElems, getterIfNoArguments) {
var originalJqFn = jQuery.fn[name];
originalJqFn = originalJqFn.$original || originalJqFn;
removePatch.$original = originalJqFn;
jQuery.fn[name] = removePatch;
function removePatch(param) {
// jshint -W040
var list = filterElems && param ? [this.filter(param)] : [this],
fireEvent = dispatchThis,
set, setIndex, setLength,
element, childIndex, childLength, children;
if (!getterIfNoArguments || param != null) {
while(list.length) {
set = list.shift();
for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) {
element = jqLite(set[setIndex]);
if (fireEvent) {
element.triggerHandler('$destroy');
} else {
fireEvent = !fireEvent;
}
for(childIndex = 0, childLength = (children = element.children()).length;
childIndex < childLength;
childIndex++) {
list.push(jQuery(children[childIndex]));
}
}
}
}
return originalJqFn.apply(this, arguments);
}
}
var SINGLE_TAG_REGEXP = /^<(\w+)\s*\/?>(?:<\/\1>|)$/;
var HTML_REGEXP = /<|&#?\w+;/;
var TAG_NAME_REGEXP = /<([\w:]+)/;
@@ -159,26 +201,22 @@ function jqLiteIsTextNode(html) {
return !HTML_REGEXP.test(html);
}
function jqLiteAcceptsData(node) {
// The window object can accept data but has no nodeType
// Otherwise we are only interested in elements (1) and documents (9)
return !node.nodeType || node.nodeType === 1 || node.nodeType === 9;
}
function jqLiteBuildFragment(html, context) {
var elem, tmp, tag, wrap,
fragment = context.createDocumentFragment(),
nodes = [], i;
nodes = [], i, j, jj;
if (jqLiteIsTextNode(html)) {
// Convert non-html into a text node
nodes.push(context.createTextNode(html));
} else {
tmp = fragment.appendChild(context.createElement('div'));
// Convert html into DOM nodes
tmp = tmp || fragment.appendChild(context.createElement("div"));
tag = (TAG_NAME_REGEXP.exec(html) || ["", ""])[1].toLowerCase();
wrap = wrapMap[tag] || wrapMap._default;
tmp.innerHTML = wrap[1] + html.replace(XHTML_TAG_REGEXP, "<$1></$2>") + wrap[2];
tmp.innerHTML = '<div>&#160;</div>' +
wrap[1] + html.replace(XHTML_TAG_REGEXP, "<$1></$2>") + wrap[2];
tmp.removeChild(tmp.firstChild);
// Descend through wrappers to the right content
i = wrap[0];
@@ -186,7 +224,7 @@ function jqLiteBuildFragment(html, context) {
tmp = tmp.lastChild;
}
nodes = concat(nodes, tmp.childNodes);
for (j=0, jj=tmp.childNodes.length; j<jj; ++j) nodes.push(tmp.childNodes[j]);
tmp = fragment.firstChild;
tmp.textContent = "";
@@ -195,11 +233,7 @@ function jqLiteBuildFragment(html, context) {
// Remove wrapper from fragment
fragment.textContent = "";
fragment.innerHTML = ""; // Clear inner HTML
forEach(nodes, function(node) {
fragment.appendChild(node);
});
return fragment;
return nodes;
}
function jqLiteParseHTML(html, context) {
@@ -210,11 +244,7 @@ function jqLiteParseHTML(html, context) {
return [context.createElement(parsed[1])];
}
if ((parsed = jqLiteBuildFragment(html, context))) {
return parsed.childNodes;
}
return [];
return jqLiteBuildFragment(html, context);
}
/////////////////////////////////////////////
@@ -234,6 +264,8 @@ function JQLite(element) {
if (isString(element)) {
jqLiteAddNodes(this, jqLiteParseHTML(element));
var fragment = jqLite(document.createDocumentFragment());
fragment.append(this);
} else {
jqLiteAddNodes(this, element);
}
@@ -243,16 +275,10 @@ function jqLiteClone(element) {
return element.cloneNode(true);
}
function jqLiteDealoc(element, onlyDescendants){
if (!onlyDescendants) jqLiteRemoveData(element);
if (element.childNodes && element.childNodes.length) {
// we use querySelectorAll because documentFragments don't have getElementsByTagName
var descendants = element.getElementsByTagName ? sliceArgs(element.getElementsByTagName('*')) :
element.querySelectorAll ? element.querySelectorAll('*') : [];
for (var i = 0, l = descendants.length; i < l; i++) {
jqLiteRemoveData(descendants[i]);
}
function jqLiteDealoc(element){
jqLiteRemoveData(element);
for ( var i = 0, children = element.childNodes || []; i < children.length; i++) {
jqLiteDealoc(children[i]);
}
}
@@ -316,29 +342,27 @@ function jqLiteExpandoStore(element, key, value) {
}
function jqLiteData(element, key, value) {
if (jqLiteAcceptsData(element)) {
var data = jqLiteExpandoStore(element, 'data'),
isSetter = isDefined(value),
keyDefined = !isSetter && isDefined(key),
isSimpleGetter = keyDefined && !isObject(key);
var data = jqLiteExpandoStore(element, 'data'),
isSetter = isDefined(value),
keyDefined = !isSetter && isDefined(key),
isSimpleGetter = keyDefined && !isObject(key);
if (!data && !isSimpleGetter) {
jqLiteExpandoStore(element, 'data', data = {});
}
if (!data && !isSimpleGetter) {
jqLiteExpandoStore(element, 'data', data = {});
}
if (isSetter) {
data[key] = value;
} else {
if (keyDefined) {
if (isSimpleGetter) {
// don't create data in this case.
return data && data[key];
} else {
extend(data, key);
}
if (isSetter) {
data[key] = value;
} else {
if (keyDefined) {
if (isSimpleGetter) {
// don't create data in this case.
return data && data[key];
} else {
return data;
extend(data, key);
}
} else {
return data;
}
}
}
@@ -377,35 +401,17 @@ function jqLiteAddClass(element, cssClasses) {
}
}
function jqLiteAddNodes(root, elements) {
// THIS CODE IS VERY HOT. Don't make changes without benchmarking.
if (elements) {
// if a Node (the most common case)
if (elements.nodeType) {
root[root.length++] = elements;
} else {
var length = elements.length;
// if an Array or NodeList and not a Window
if (typeof length === 'number' && elements.window !== elements) {
if (length) {
if (elements.item) {
// convert NodeList to an Array to make PhantomJS 1.x happy
elements = slice.call(elements);
}
push.apply(root, elements);
}
} else {
root[root.length++] = elements;
}
elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements))
? elements
: [ elements ];
for(var i=0; i < elements.length; i++) {
root.push(elements[i]);
}
}
}
function jqLiteController(element, name) {
return jqLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller');
}
@@ -431,7 +437,9 @@ function jqLiteInheritedData(element, name, value) {
}
function jqLiteEmpty(element) {
jqLiteDealoc(element, true);
for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {
jqLiteDealoc(childNodes[i]);
}
while (element.firstChild) {
element.removeChild(element.firstChild);
}
@@ -488,25 +496,15 @@ forEach('multiple,selected,checked,disabled,readOnly,required,open'.split(','),
});
var BOOLEAN_ELEMENTS = {};
forEach('input,select,option,textarea,button,form,details'.split(','), function(value) {
BOOLEAN_ELEMENTS[value] = true;
BOOLEAN_ELEMENTS[uppercase(value)] = true;
});
var ALIASED_ATTR = {
'ngMinlength' : 'minlength',
'ngMaxlength' : 'maxlength',
'ngPattern' : 'pattern'
};
function getBooleanAttrName(element, name) {
// check dom last since we will most likely fail on name
var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()];
// booleanAttr is here twice to minimize DOM access
return booleanAttr && BOOLEAN_ELEMENTS[nodeName_(element)] && booleanAttr;
}
function getAliasedAttrName(element, name) {
var nodeName = element.nodeName;
return (nodeName === 'INPUT' || nodeName === 'TEXTAREA') && ALIASED_ATTR[name];
return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr;
}
forEach({
@@ -604,21 +602,29 @@ forEach({
},
text: (function() {
var NODE_TYPE_TEXT_PROPERTY = [];
if (msie < 9) {
NODE_TYPE_TEXT_PROPERTY[1] = 'innerText'; /** Element **/
NODE_TYPE_TEXT_PROPERTY[3] = 'nodeValue'; /** Text **/
} else {
NODE_TYPE_TEXT_PROPERTY[1] = /** Element **/
NODE_TYPE_TEXT_PROPERTY[3] = 'textContent'; /** Text **/
}
getText.$dv = '';
return getText;
function getText(element, value) {
var textProp = NODE_TYPE_TEXT_PROPERTY[element.nodeType];
if (isUndefined(value)) {
var nodeType = element.nodeType;
return (nodeType === 1 || nodeType === 3) ? element.textContent : '';
return textProp ? element[textProp] : '';
}
element.textContent = value;
element[textProp] = value;
}
})(),
val: function(element, value) {
if (isUndefined(value)) {
if (element.multiple && nodeName_(element) === 'select') {
if (nodeName_(element) === 'SELECT' && element.multiple) {
var result = [];
forEach(element.options, function (option) {
if (option.selected) {
@@ -636,7 +642,9 @@ forEach({
if (isUndefined(value)) {
return element.innerHTML;
}
jqLiteDealoc(element, true);
for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) {
jqLiteDealoc(childNodes[i]);
}
element.innerHTML = value;
},
@@ -756,14 +764,11 @@ function createEventHandler(element, events) {
forEach({
removeData: jqLiteRemoveData,
dealoc: jqLiteDealoc,
on: function onFn(element, type, fn, unsupported){
if (isDefined(unsupported)) throw jqLiteMinErr('onargs', 'jqLite#on() does not support the `selector` or `eventData` parameters');
// Do not add event handlers to non-elements because they will not be cleaned up.
if (!jqLiteAcceptsData(element)) {
return;
}
var events = jqLiteExpandoStore(element, 'events'),
handle = jqLiteExpandoStore(element, 'handle');
+3 -8
View File
@@ -99,19 +99,15 @@ function setupModuleLoader(window) {
/** @type {!Array.<Array.<*>>} */
var invokeQueue = [];
/** @type {!Array.<Function>} */
var configBlocks = [];
/** @type {!Array.<Function>} */
var runBlocks = [];
var config = invokeLater('$injector', 'invoke', 'push', configBlocks);
var config = invokeLater('$injector', 'invoke');
/** @type {angular.Module} */
var moduleInstance = {
// Private state
_invokeQueue: invokeQueue,
_configBlocks: configBlocks,
_runBlocks: runBlocks,
/**
@@ -303,10 +299,9 @@ function setupModuleLoader(window) {
* @param {String=} insertMethod
* @returns {angular.Module}
*/
function invokeLater(provider, method, insertMethod, queue) {
if (!queue) queue = invokeQueue;
function invokeLater(provider, method, insertMethod) {
return function() {
queue[insertMethod || 'push']([provider, method, arguments]);
invokeQueue[insertMethod || 'push']([provider, method, arguments]);
return moduleInstance;
};
}
+12 -14
View File
@@ -17,26 +17,24 @@
* This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`.
*
* @example
<example module="anchorScrollExample">
<example>
<file name="index.html">
<div id="scrollArea" ng-controller="ScrollController">
<div id="scrollArea" ng-controller="ScrollCtrl">
<a ng-click="gotoBottom()">Go to bottom</a>
<a id="bottom"></a> You're at the bottom!
</div>
</file>
<file name="script.js">
angular.module('anchorScrollExample', [])
.controller('ScrollController', ['$scope', '$location', '$anchorScroll',
function ($scope, $location, $anchorScroll) {
$scope.gotoBottom = function() {
// set the location.hash to the id of
// the element you wish to scroll to.
$location.hash('bottom');
function ScrollCtrl($scope, $location, $anchorScroll) {
$scope.gotoBottom = function (){
// set the location.hash to the id of
// the element you wish to scroll to.
$location.hash('bottom');
// call $anchorScroll()
$anchorScroll();
};
}]);
// call $anchorScroll()
$anchorScroll();
};
}
</file>
<file name="style.css">
#scrollArea {
@@ -69,7 +67,7 @@ function $AnchorScrollProvider() {
function getFirstAnchor(list) {
var result = null;
forEach(list, function(element) {
if (!result && nodeName_(element) === 'a') result = element;
if (!result && lowercase(element.nodeName) === 'a') result = element;
});
return result;
}
+14 -15
View File
@@ -111,9 +111,8 @@ var $AnimateProvider = ['$provide', function($provide) {
* @ngdoc method
* @name $animate#enter
* @kind function
* @description Inserts the element into the DOM either after the `after` element or
* as the first child within the `parent` element. Once complete, the done() callback
* will be fired (if provided).
* @description Inserts the element into the DOM either after the `after` element or within
* the `parent` element. Once complete, the done() callback will be fired (if provided).
* @param {DOMElement} element the element which will be inserted into the DOM
* @param {DOMElement} parent the parent element which will append the element as
* a child (if the after element is not present)
@@ -123,11 +122,15 @@ var $AnimateProvider = ['$provide', function($provide) {
* inserted into the DOM
*/
enter : function(element, parent, after, done) {
after
? after.after(element)
: parent.prepend(element);
if (after) {
after.after(element);
} else {
if (!parent || !parent[0]) {
parent = after.parent();
}
parent.append(element);
}
async(done);
return noop;
},
/**
@@ -144,7 +147,6 @@ var $AnimateProvider = ['$provide', function($provide) {
leave : function(element, done) {
element.remove();
async(done);
return noop;
},
/**
@@ -168,7 +170,7 @@ var $AnimateProvider = ['$provide', function($provide) {
move : function(element, parent, after, done) {
// Do not remove element before insert. Removing will cause data associated with the
// element to be dropped. Insert will implicitly do the remove.
return this.enter(element, parent, after, done);
this.enter(element, parent, after, done);
},
/**
@@ -185,14 +187,13 @@ var $AnimateProvider = ['$provide', function($provide) {
* className value has been added to the element
*/
addClass : function(element, className, done) {
className = !isString(className)
? (isArray(className) ? className.join(' ') : '')
: className;
className = isString(className) ?
className :
isArray(className) ? className.join(' ') : '';
forEach(element, function (element) {
jqLiteAddClass(element, className);
});
async(done);
return noop;
},
/**
@@ -216,7 +217,6 @@ var $AnimateProvider = ['$provide', function($provide) {
jqLiteRemoveClass(element, className);
});
async(done);
return noop;
},
/**
@@ -239,7 +239,6 @@ var $AnimateProvider = ['$provide', function($provide) {
jqLiteRemoveClass(element, remove);
});
async(done);
return noop;
},
enabled : noop
+5 -4
View File
@@ -280,15 +280,16 @@ function Browser(window, document, $log, $sniffer) {
* @returns {Object} Hash of all cookies (if called without any parameter)
*/
self.cookies = function(name, value) {
/* global escape: false, unescape: false */
var cookieLength, cookieArray, cookie, i, index;
if (name) {
if (value === undefined) {
rawDocument.cookie = encodeURIComponent(name) + "=;path=" + cookiePath +
rawDocument.cookie = escape(name) + "=;path=" + cookiePath +
";expires=Thu, 01 Jan 1970 00:00:00 GMT";
} else {
if (isString(value)) {
cookieLength = (rawDocument.cookie = encodeURIComponent(name) + '=' + encodeURIComponent(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:
@@ -312,12 +313,12 @@ function Browser(window, document, $log, $sniffer) {
cookie = cookieArray[i];
index = cookie.indexOf('=');
if (index > 0) { //ignore nameless cookies
name = decodeURIComponent(cookie.substring(0, index));
name = unescape(cookie.substring(0, index));
// the first value that is seen for a cookie is the most
// specific one. values for the same cookie name that
// follow are for less specific paths.
if (lastCookies[name] === undefined) {
lastCookies[name] = decodeURIComponent(cookie.substring(index + 1));
lastCookies[name] = unescape(cookie.substring(index + 1));
}
}
}
+60 -150
View File
@@ -111,13 +111,6 @@
* The directive definition object provides instructions to the {@link ng.$compile
* compiler}. The attributes are:
*
* #### `multiElement`
* When this property is set to true, the HTML compiler will collect DOM nodes between
* nodes with the attributes `directive-name-start` and `directive-name-end`, and group them
* together as the directive elements. It is recomended that this feature be used on directives
* which are not strictly behavioural (such as {@link api/ng.directive:ngClick ngClick}), and which
* do not manipulate or replace child nodes (such as {@link api/ng.directive:ngInclude ngInclude}).
*
* #### `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
@@ -213,25 +206,12 @@
* String of subset of `EACM` which restricts the directive to a specific directive
* declaration style. If omitted, the default (attributes only) is used.
*
* * `E` - Element name (default): `<my-directive></my-directive>`
* * `E` - Element name: `<my-directive></my-directive>`
* * `A` - Attribute (default): `<div my-directive="exp"></div>`
* * `C` - Class: `<div class="my-directive: exp;"></div>`
* * `M` - Comment: `<!-- directive: my-directive exp -->`
*
*
* #### `type`
* String representing the document type used by the markup. This is useful for templates where the root
* node is non-HTML content (such as SVG or MathML). The default value is "html".
*
* * `html` - All root template nodes are HTML, and don't need to be wrapped. Root nodes may also be
* top-level elements such as `<svg>` or `<math>`.
* * `svg` - The template contains only SVG content, and must be wrapped in an `<svg>` node prior to
* processing.
* * `math` - The template contains only MathML content, and must be wrapped in an `<math>` node prior to
* processing.
*
* If no `type` is specified, then the type is considered to be html.
*
* #### `template`
* HTML markup that may:
* * Replace the contents of the directive's element (default).
@@ -537,8 +517,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
var hasDirectives = {},
Suffix = 'Directive',
COMMENT_DIRECTIVE_REGEXP = /^\s*directive\:\s*([\d\w_\-]+)\s+(.*)$/,
CLASS_DIRECTIVE_REGEXP = /(([\d\w_\-]+)(?:\:([^;]+))?;?)/,
ALL_OR_NOTHING_ATTRS = makeMap('ngSrc,ngSrcset,src,srcset');
CLASS_DIRECTIVE_REGEXP = /(([\d\w_\-]+)(?:\:([^;]+))?;?)/;
// Ref: http://developers.whatwg.org/webappapis.html#event-handler-idl-attributes
// The assumption is that future DOM event attribute names will begin with
@@ -581,7 +560,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
directive.index = index;
directive.name = directive.name || name;
directive.require = directive.require || (directive.controller && directive.name);
directive.restrict = directive.restrict || 'EA';
directive.restrict = directive.restrict || 'A';
directives.push(directive);
} catch (e) {
$exceptionHandler(e);
@@ -745,19 +724,13 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
//is set through this function since it may cause $updateClass to
//become unstable.
var node = this.$$element[0],
booleanKey = getBooleanAttrName(node, key),
aliasedKey = getAliasedAttrName(node, key),
observer = key,
var booleanKey = getBooleanAttrName(this.$$element[0], key),
normalizedVal,
nodeName;
if (booleanKey) {
this.$$element.prop(key, value);
attrName = booleanKey;
} else if(aliasedKey) {
this[aliasedKey] = value;
observer = aliasedKey;
}
this[key] = value;
@@ -775,8 +748,8 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
nodeName = nodeName_(this.$$element);
// sanitize a[href] and img[src] values
if ((nodeName === 'a' && key === 'href') ||
(nodeName === 'img' && key === 'src')) {
if ((nodeName === 'A' && key === 'href') ||
(nodeName === 'IMG' && key === 'src')) {
this[key] = value = $$sanitizeUri(value, key === 'src');
}
@@ -790,7 +763,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
// fire observers
var $$observers = this.$$observers;
$$observers && forEach($$observers[observer], function(fn) {
$$observers && forEach($$observers[key], function(fn) {
try {
fn(value);
} catch (e) {
@@ -816,7 +789,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
* @param {function(interpolatedValue)} fn Function that will be called whenever
the interpolated value of the attribute changes.
* See the {@link guide/directive#Attributes Directives} guide for more info.
* @returns {function()} Returns a deregistration function for this observer.
* @returns {function()} the `fn` parameter.
*/
$observe: function(key, fn) {
var attrs = this,
@@ -830,10 +803,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
fn(attrs[key]);
}
});
return function() {
arrayRemove(listeners, fn);
};
return fn;
}
};
@@ -881,7 +851,14 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
$linkNode.data('$' + name + 'Controller', instance);
});
$linkNode.data('$scope', scope);
// Attach scope only to non-text nodes.
for(var i = 0, ii = $linkNode.length; i<ii; i++) {
var node = $linkNode[i],
nodeType = node.nodeType;
if (nodeType === 1 /* element */ || nodeType === 9 /* document */) {
$linkNode.eq(i).data('$scope', scope);
}
}
if (cloneConnectFn) cloneConnectFn($linkNode, scope);
if (compositeLinkFn) compositeLinkFn(scope, $linkNode, $linkNode, parentBoundTranscludeFn);
@@ -1038,7 +1015,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
case 1: /* Element */
// use the node name: <directive>
addDirective(directives,
directiveNormalize(nodeName_(node)), 'E', maxPriority, ignoreDirective);
directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority, ignoreDirective);
// iterate over the attributes
for (var attr, name, nName, ngAttrName, value, isNgAttr, nAttrs = node.attributes,
@@ -1058,12 +1035,10 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
}
var directiveNName = ngAttrName.replace(/(Start|End)$/, '');
if (directiveIsMultiElement(directiveNName)) {
if (ngAttrName === directiveNName + 'Start') {
attrStartName = name;
attrEndName = name.substr(0, name.length - 5) + 'end';
name = name.substr(0, name.length - 6);
}
if (ngAttrName === directiveNName + 'Start') {
attrStartName = name;
attrEndName = name.substr(0, name.length - 5) + 'end';
name = name.substr(0, name.length - 6);
}
nName = directiveNormalize(name.toLowerCase());
@@ -1227,25 +1202,17 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
}
if (directiveValue = directive.scope) {
newScopeDirective = newScopeDirective || directive;
// skip the check for directives with async templates, we'll check the derived sync
// directive when the template arrives
if (!directive.templateUrl) {
assertNoDuplicate('new/isolated scope', newIsolateScopeDirective, directive,
$compileNode);
if (isObject(directiveValue)) {
// This directive is trying to add an isolated scope.
// Check that there is no scope of any kind already
assertNoDuplicate('new/isolated scope', newIsolateScopeDirective || newScopeDirective,
directive, $compileNode);
newIsolateScopeDirective = directive;
} else {
// This directive is trying to add a child scope.
// Check that there is no isolated scope already
assertNoDuplicate('new/isolated scope', newIsolateScopeDirective, directive,
$compileNode);
}
}
newScopeDirective = newScopeDirective || directive;
}
directiveName = directive.name;
@@ -1313,7 +1280,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
if (jqLiteIsTextNode(directiveValue)) {
$template = [];
} else {
$template = jqLite(wrapTemplate(directive.type, trim(directiveValue)));
$template = jqLite(trim(directiveValue));
}
compileNode = $template[0];
@@ -1517,7 +1484,8 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
attrs[attrName], newIsolateScopeDirective.name);
};
lastValue = isolateScope[scopeName] = parentGet(scope);
var unwatch = scope.$watch($parse(attrs[attrName], function parentValueWatch(parentValue) {
isolateScope.$watch(function parentValueWatch() {
var parentValue = parentGet(scope);
if (!compare(parentValue, isolateScope[scopeName])) {
// we are out of sync and need to copy
if (!compare(parentValue, lastValue)) {
@@ -1529,8 +1497,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
}
}
return lastValue = parentValue;
}), null, parentGet.literal);
isolateScope.$on('$destroy', unwatch);
}, null, parentGet.literal);
break;
case '&':
@@ -1675,27 +1642,6 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
}
/**
* looks up the directive and returns true if it is a multi-element directive,
* and therefore requires DOM nodes between -start and -end markers to be grouped
* together.
*
* @param {string} name name of the directive to look up.
* @returns true if directive was registered as multi-element.
*/
function directiveIsMultiElement(name) {
if (hasDirectives.hasOwnProperty(name)) {
for(var directive, directives = $injector.get(name + Suffix),
i = 0, ii = directives.length; i<ii; i++) {
directive = directives[i];
if (directive.multiElement) {
return true;
}
}
}
return false;
}
/**
* When the element is replaced with HTML template then the new attributes
* on the template need to be merged with the existing attributes in the DOM.
@@ -1751,8 +1697,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
}),
templateUrl = (isFunction(origAsyncDirective.templateUrl))
? origAsyncDirective.templateUrl($compileNode, tAttrs)
: origAsyncDirective.templateUrl,
type = origAsyncDirective.type;
: origAsyncDirective.templateUrl;
$compileNode.empty();
@@ -1766,7 +1711,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
if (jqLiteIsTextNode(content)) {
$template = [];
} else {
$template = jqLite(wrapTemplate(type, trim(content)));
$template = jqLite(trim(content));
}
compileNode = $template[0];
@@ -1873,45 +1818,31 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
}
function addTextInterpolateDirective(directives, text) {
var interpolateFn = $interpolate(text, true);
if (interpolateFn) {
directives.push({
priority: 0,
compile: function textInterpolateCompileFn(templateNode) {
// when transcluding a template that has bindings in the root
// then we don't have a parent and should do this in the linkFn
var parent = templateNode.parent(), hasCompileParent = parent.length;
if (hasCompileParent) safeAddClass(templateNode.parent(), 'ng-binding');
function addTextInterpolateDirective(directives, text) {
var interpolateFn = $interpolate(text, true);
if (interpolateFn) {
directives.push({
priority: 0,
compile: function textInterpolateCompileFn(templateNode) {
// when transcluding a template that has bindings in the root
// then we don't have a parent and should do this in the linkFn
var parent = templateNode.parent(), hasCompileParent = parent.length;
if (hasCompileParent) safeAddClass(templateNode.parent(), 'ng-binding');
return function textInterpolateLinkFn(scope, node) {
var parent = node.parent(),
return function textInterpolateLinkFn(scope, node) {
var parent = node.parent(),
bindings = parent.data('$binding') || [];
bindings.push(interpolateFn);
parent.data('$binding', bindings);
if (!hasCompileParent) safeAddClass(parent, 'ng-binding');
scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {
node[0].nodeValue = value;
});
};
}
});
bindings.push(interpolateFn);
parent.data('$binding', bindings);
if (!hasCompileParent) safeAddClass(parent, 'ng-binding');
scope.$watch(interpolateFn, function interpolateFnWatchAction(value) {
node[0].nodeValue = value;
});
};
}
});
}
}
}
function wrapTemplate(type, template) {
type = lowercase(type || 'html');
switch(type) {
case 'svg':
case 'math':
var wrapper = document.createElement('div');
wrapper.innerHTML = '<'+type+'>'+template+'</'+type+'>';
return wrapper.childNodes[0].childNodes;
default:
return template;
}
}
function getTrustedContext(node, attrNormalizedName) {
@@ -1921,8 +1852,8 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
var tag = nodeName_(node);
// maction[xlink:href] can source SVG. It's not limited to <maction>.
if (attrNormalizedName == "xlinkHref" ||
(tag == "form" && attrNormalizedName == "action") ||
(tag != "img" && (attrNormalizedName == "src" ||
(tag == "FORM" && attrNormalizedName == "action") ||
(tag != "IMG" && (attrNormalizedName == "src" ||
attrNormalizedName == "ngSrc"))) {
return $sce.RESOURCE_URL;
}
@@ -1936,7 +1867,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
if (!interpolateFn) return;
if (name === "multiple" && nodeName_(node) === "select") {
if (name === "multiple" && nodeName_(node) === "SELECT") {
throw $compileMinErr("selmulti",
"Binding to the 'multiple' attribute is not supported. Element: {0}",
startingTag(node));
@@ -1957,18 +1888,15 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
// we need to interpolate again, in case the attribute value has been updated
// (e.g. by another directive's compile function)
interpolateFn = $interpolate(attr[name], true, getTrustedContext(node, name),
ALL_OR_NOTHING_ATTRS[name]);
interpolateFn = $interpolate(attr[name], true, getTrustedContext(node, name));
// if attribute was updated so that there is no interpolation going on we don't want to
// register any observers
if (!interpolateFn) return;
// initialize attr object so that it's ready in case we need the value for isolate
// scope initialization, otherwise the value would not be available from isolate
// directive's linking fn during linking phase
// TODO(i): this should likely be attr.$set(name, iterpolateFn(scope) so that we reset the
// actual attr value
attr[name] = interpolateFn(scope);
($$observers[name] || ($$observers[name] = [])).$$inter = true;
(attr.$$observers && attr.$$observers[name].$$scope || scope).
$watch(interpolateFn, function interpolateFnWatchAction(newValue, oldValue) {
@@ -2031,25 +1959,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
}
var fragment = document.createDocumentFragment();
fragment.appendChild(firstElementToRemove);
// Copy over user data (that includes Angular's $scope etc.). Don't copy private
// data here because there's no public interface in jQuery to do that and copying over
// event listeners (which is the main use of private data) wouldn't work anyway.
jqLite(newNode).data(jqLite(firstElementToRemove).data());
// Remove data of the replaced element. We cannot just call .remove()
// on the element it since that would deallocate scope that is needed
// for the new node. Instead, remove the data "manually".
if (!jQuery) {
delete jqLite.cache[firstElementToRemove[jqLite.expando]];
} else {
// jQuery 2.x doesn't expose the data storage. Use jQuery.cleanData to clean up after the replaced
// element. Note that we need to use the original method here and not the one monkey-patched by Angular
// since the patched method emits the $destroy event causing the scope to be trashed and we do need
// the very same scope to work with the new element.
jQuery.cleanData.$$original([firstElementToRemove]);
}
newNode[jqLite.expando] = firstElementToRemove[jqLite.expando];
for (var k = 1, kk = elementsToRemove.length; k < kk; k++) {
var element = elementsToRemove[k];
jqLite(element).remove(); // must do this way to clean up expando
+3 -15
View File
@@ -12,7 +12,6 @@
*/
function $ControllerProvider() {
var controllers = {},
globals = false,
CNTRL_REG = /^(\S+)(\s+as\s+(\w+))?$/;
@@ -33,15 +32,6 @@ function $ControllerProvider() {
}
};
/**
* @ngdoc method
* @name $controllerProvider#allowGlobals
* @description If called, allows `$controller` to find controller constructors on `window`
*/
this.allowGlobals = function() {
globals = true;
};
this.$get = ['$injector', '$window', function($injector, $window) {
@@ -56,8 +46,7 @@ function $ControllerProvider() {
*
* * check if a controller with given name is registered via `$controllerProvider`
* * check if evaluating the string on the current scope returns a constructor
* * if $controllerProvider#allowGlobals, check `window[constructor]` on the global
* `window` object (not recommended)
* * check `window[constructor]` on the global `window` object
*
* @param {Object} locals Injection locals for Controller.
* @return {Object} Instance of given controller.
@@ -77,13 +66,12 @@ function $ControllerProvider() {
identifier = match[3];
expression = controllers.hasOwnProperty(constructor)
? controllers[constructor]
: getter(locals.$scope, constructor, true) ||
(globals ? getter($window, constructor, true) : undefined);
: getter(locals.$scope, constructor, true) || getter($window, constructor, true);
assertArgFn(expression, constructor, true);
}
instance = $injector.instantiate(expression, locals, constructor);
instance = $injector.instantiate(expression, locals);
if (identifier) {
if (!(locals && typeof locals.$scope === 'object')) {
@@ -17,12 +17,12 @@
*
* The wrong way to write it:
* ```html
* <a href="http://www.gravatar.com/avatar/{{hash}}">link1</a>
* <a href="http://www.gravatar.com/avatar/{{hash}}"/>
* ```
*
* The correct way to write it:
* ```html
* <a ng-href="http://www.gravatar.com/avatar/{{hash}}">link1</a>
* <a ng-href="http://www.gravatar.com/avatar/{{hash}}"/>
* ```
*
* @element A
@@ -351,7 +351,6 @@ forEach(BOOLEAN_ATTR, function(propName, attrName) {
var normalized = directiveNormalize('ng-' + attrName);
ngAttributeAliasDirectives[normalized] = function() {
return {
restrict: 'A',
priority: 100,
link: function(scope, element, attr) {
scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {
@@ -362,29 +361,6 @@ forEach(BOOLEAN_ATTR, function(propName, attrName) {
};
});
// aliased input attrs are evaluated
forEach(ALIASED_ATTR, function(htmlAttr, ngAttr) {
ngAttributeAliasDirectives[ngAttr] = function() {
return {
priority: 100,
link: function(scope, element, attr) {
//special case ngPattern when a literal regular expression value
//is used as the expression (this way we don't have to watch anything).
if (ngAttr === "ngPattern" && attr.ngPattern.charAt(0) == "/") {
var match = attr.ngPattern.match(REGEX_STRING_REGEXP);
if (match) {
attr.$set("ngPattern", new RegExp(match[1], match[2]));
return;
}
}
scope.$watch(attr[ngAttr], function ngAttrAliasWatchAction(value) {
attr.$set(ngAttr, value);
});
}
};
};
});
// ng-src, ng-srcset, ng-href are interpolated
forEach(['src', 'srcset', 'href'], function(attrName) {
@@ -404,12 +380,8 @@ forEach(['src', 'srcset', 'href'], function(attrName) {
}
attr.$observe(normalized, function(value) {
if (!value) {
if (attrName === 'href') {
attr.$set(name, null);
}
return;
}
if (!value)
return;
attr.$set(name, value);
+9 -68
View File
@@ -1,15 +1,13 @@
'use strict';
/* global -nullFormCtrl, -SUBMITTED_CLASS */
/* global -nullFormCtrl */
var nullFormCtrl = {
$addControl: noop,
$removeControl: noop,
$setValidity: noop,
$setDirty: noop,
$setPristine: noop,
$setSubmitted: noop
},
SUBMITTED_CLASS = 'ng-submitted';
$setPristine: noop
};
/**
* @ngdoc type
@@ -62,7 +60,6 @@ function FormController(element, attrs, $scope, $animate) {
form.$pristine = true;
form.$valid = true;
form.$invalid = false;
form.$submitted = false;
parentForm.$addControl(form);
@@ -77,40 +74,6 @@ function FormController(element, attrs, $scope, $animate) {
$animate.addClass(element, (isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey);
}
/**
* @ngdoc method
* @name form.FormController#$rollbackViewValue
*
* @description
* Rollback all form controls pending updates to the `$modelValue`.
*
* Updates may be pending by a debounced event or because the input is waiting for a some future
* event defined in `ng-model-options`. This method is typically needed by the reset button of
* a form that uses `ng-model-options` to pend updates.
*/
form.$rollbackViewValue = function() {
forEach(controls, function(control) {
control.$rollbackViewValue();
});
};
/**
* @ngdoc method
* @name form.FormController#$commitViewValue
*
* @description
* Commit all form controls pending updates to the `$modelValue`.
*
* Updates may be pending by a debounced event or because the input is waiting for a some future
* event defined in `ng-model-options`. This method is rarely needed as `NgModelController`
* usually handles calling this in response to input events.
*/
form.$commitViewValue = function() {
forEach(controls, function(control) {
control.$commitViewValue();
});
};
/**
* @ngdoc method
* @name form.FormController#$addControl
@@ -231,29 +194,17 @@ function FormController(element, attrs, $scope, $animate) {
* saving or resetting it.
*/
form.$setPristine = function () {
$animate.setClass(element, PRISTINE_CLASS, DIRTY_CLASS + ' ' + SUBMITTED_CLASS);
$animate.removeClass(element, DIRTY_CLASS);
$animate.addClass(element, PRISTINE_CLASS);
form.$dirty = false;
form.$pristine = true;
form.$submitted = false;
forEach(controls, function(control) {
control.$setPristine();
});
};
/**
* @ngdoc method
* @name form.FormController#setSubmitted
*
* @description
* Sets the form to its submitted state.
*/
form.$setSubmitted = function () {
$animate.addClass(element, SUBMITTED_CLASS);
form.$submitted = true;
parentForm.$setSubmitted();
};
}
/**
* @ngdoc directive
* @name ngForm
@@ -302,7 +253,6 @@ function FormController(element, attrs, $scope, $animate) {
* - `ng-invalid` is set if the form is invalid.
* - `ng-pristine` is set if the form is pristine.
* - `ng-dirty` is set if the form is dirty.
* - `ng-submitted` is set if the form was submitted.
*
* Keep in mind that ngAnimate can detect each of these classes when added and removed.
*
@@ -336,10 +286,6 @@ function FormController(element, attrs, $scope, $animate) {
* hitting enter in any of the input fields will trigger the click handler on the *first* button or
* input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`)
*
* Any pending `ngModelOptions` changes will take place immediately when an enclosing form is
* submitted. Note that `ngClick` events will occur before the model is updated. Use `ngSubmit`
* to have access to the updated model.
*
* @param {string=} name Name of the form. If specified, the form controller will be published into
* related scope, under this name.
*
@@ -436,24 +382,19 @@ var formDirectiveFactory = function(isNgForm) {
// IE 9 is not affected because it doesn't fire a submit event and try to do a full
// page reload if the form was destroyed by submission of the form via a click handler
// on a button in the form. Looks like an IE9 specific bug.
var handleFormSubmission = function(event) {
scope.$apply(function() {
controller.$commitViewValue();
controller.$setSubmitted();
});
var preventDefaultListener = function(event) {
event.preventDefault
? event.preventDefault()
: event.returnValue = false; // IE
};
addEventListenerFn(formElement[0], 'submit', handleFormSubmission);
addEventListenerFn(formElement[0], 'submit', preventDefaultListener);
// unregister the preventDefault listener so that we don't not leak memory but in a
// way that will achieve the prevention of the default action.
formElement.on('$destroy', function() {
$timeout(function() {
removeEventListenerFn(formElement[0], 'submit', handleFormSubmission);
removeEventListenerFn(formElement[0], 'submit', preventDefaultListener);
}, 0, false);
});
}
+214 -1304
View File
File diff suppressed because it is too large Load Diff
+8 -9
View File
@@ -178,20 +178,19 @@ var ngBindTemplateDirective = ['$interpolate', function($interpolate) {
*/
var ngBindHtmlDirective = ['$sce', '$parse', function($sce, $parse) {
return {
restrict: 'A',
compile: function (tElement, tAttrs) {
compile: function (tElement) {
tElement.addClass('ng-binding');
return function (scope, element, attr) {
element.data('$binding', attr.ngBindHtml);
var parsed = $parse(attr.ngBindHtml);
var changeDetector = $parse(attr.ngBindHtml, function getStringValue(value) {
return (value || '').toString();
});
scope.$watch(changeDetector, function ngBindHtmlWatchAction() {
// we re-evaluate the expr because we want a TrustedValueHolderType
// for $sce, not a string
var parsed = $parse(attr.ngBindHtml);
function getStringValue() {
return (parsed(scope) || '').toString();
}
scope.$watch(getStringValue, function ngBindHtmlWatchAction(value) {
element.html($sce.getTrustedHtml(parsed(scope)) || '');
});
};
+4 -11
View File
@@ -23,16 +23,10 @@
*
* @element ANY
* @scope
* @param {expression} ngController Name of a constructor function registered with the current
* {@link ng.$controllerProvider $controllerProvider} or an {@link guide/expression expression}
* that on the current scope evaluates to a constructor function.
*
* The controller instance can be published into a scope property by specifying
* `ng-controller="as propertyName"`.
*
* If the current `$controllerProvider` is configured to use globals (via
* {@link ng.$controllerProvider#allowGlobals `$controllerProvider.allowGlobals()` }), this may
* also be the name of a globally accessible constructor function (not recommended).
* @param {expression} ngController Name of a globally accessible constructor function or an
* {@link guide/expression expression} that on the current scope evaluates to a
* constructor function. The controller instance can be published into a scope property
* by specifying `as propertyName`.
*
* @example
* Here is a simple form for editing user contact information. Adding, removing, clearing, and
@@ -227,7 +221,6 @@
*/
var ngControllerDirective = [function() {
return {
restrict: 'A',
scope: true,
controller: '@',
priority: 500
-1
View File
@@ -43,7 +43,6 @@ forEach(
var directiveName = directiveNormalize('ng-' + name);
ngEventDirectives[directiveName] = ['$parse', function($parse) {
return {
restrict: 'A',
compile: function($element, attr) {
var fn = $parse(attr[directiveName]);
return function ngEventHandler(scope, element) {
+3 -4
View File
@@ -78,7 +78,6 @@
*/
var ngIfDirective = ['$animate', function($animate) {
return {
multiElement: true,
transclude: 'element',
priority: 600,
terminal: true,
@@ -88,10 +87,10 @@ var ngIfDirective = ['$animate', function($animate) {
var block, childScope, previousElements;
$scope.$watch($attr.ngIf, function ngIfWatchAction(value) {
if (value) {
if (toBoolean(value)) {
if (!childScope) {
$transclude(function (clone, newScope) {
childScope = newScope;
childScope = $scope.$new();
$transclude(childScope, function (clone) {
clone[clone.length++] = document.createComment(' end ngIf: ' + $attr.ngIf + ' ');
// Note: We only need the first/last node of the cloned nodes.
// However, we need to keep the reference to the jqlite wrapper as it might be changed later
+1 -13
View File
@@ -160,15 +160,6 @@
* @description
* Emitted every time the ngInclude content is reloaded.
*/
/**
* @ngdoc event
* @name ngInclude#$includeContentError
* @eventType emit on the scope ngInclude was declared in
* @description
* Emitted when a template HTTP request yields an erronous response (status < 200 || status > 299)
*/
var ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$animate', '$sce',
function($http, $templateCache, $anchorScroll, $animate, $sce) {
return {
@@ -237,10 +228,7 @@ var ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$animate'
currentScope.$emit('$includeContentLoaded');
scope.$eval(onloadExp);
}).error(function() {
if (thisChangeId === changeCounter) {
cleanupLastIncludeContent();
scope.$emit('$includeContentError');
}
if (thisChangeId === changeCounter) cleanupLastIncludeContent();
});
scope.$emit('$includeContentRequested');
} else {
+1 -1
View File
@@ -205,7 +205,7 @@ var ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interp
//if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise,
//check it against pluralization rules in $locale service
if (!(value in whens)) value = $locale.pluralCat(value - offset);
return whensExpFns[value](scope);
return whensExpFns[value](scope, element, true);
} else {
return '';
}
+29 -42
View File
@@ -100,13 +100,6 @@
* For example: `item in items` is equivalent to `item in items track by $id(item)`. This implies that the DOM elements
* will be associated by item identity in the array.
*
* * `variable in expression as alias_expression` You can also provide an optional alias expression which will then store the
* intermediate results of the repeater after the filters have been applied. Typically this is used to render a special message
* when a filter is active on the repeater, but the filtered result set is empty.
*
* For example: `item in items | filter:x as results` will store the fragment of the repeated items as `results`, but only after
* the items have been processed through the filter.
*
* For example: `item in items track by $id(item)`. A built in `$id()` function can be used to assign a unique
* `$$hashKey` property to each item in the array. This property is then used as a key to associated DOM elements
* with the corresponding item in the array by identity. Moving the same object in array would move the DOM
@@ -139,12 +132,9 @@
I have {{friends.length}} friends. They are:
<input type="search" ng-model="q" placeholder="filter friends..." />
<ul class="example-animate-container">
<li class="animate-repeat" ng-repeat="friend in friends | filter:q as results">
<li class="animate-repeat" ng-repeat="friend in friends | filter:q">
[{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old.
</li>
<li class="animate-repeat" ng-if="results.length == 0">
<strong>No results found...</strong>
</li>
</ul>
</div>
</file>
@@ -212,16 +202,14 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
var NG_REMOVED = '$$NG_REMOVED';
var ngRepeatMinErr = minErr('ngRepeat');
return {
restrict: 'A',
multiElement: true,
transclude: 'element',
priority: 1000,
terminal: true,
$$tlb: true,
link: function($scope, $element, $attr, ctrl, $transclude){
var expression = $attr.ngRepeat;
var match = expression.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+track\s+by\s+([\s\S]+?))?\s*$/),
trackByExp, trackByExpGetter, aliasAs, trackByIdExpFn, trackByIdArrayFn, trackByIdObjFn,
var match = expression.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/),
trackByExp, trackByExpGetter, trackByIdExpFn, trackByIdArrayFn, trackByIdObjFn,
lhs, rhs, valueIdentifier, keyIdentifier,
hashFnLocals = {$id: hashKey};
@@ -232,8 +220,7 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
lhs = match[1];
rhs = match[2];
aliasAs = match[3];
trackByExp = match[4];
trackByExp = match[3];
if (trackByExp) {
trackByExpGetter = $parse(trackByExp);
@@ -277,6 +264,7 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
// lastBlockMap on the next iteration.
nextBlockMap = {},
arrayLength,
childScope,
key, value, // key/value of iteration
trackById,
trackByIdFn,
@@ -285,21 +273,6 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
nextBlockOrder = [],
elementsToRemove;
if (aliasAs) {
$scope[aliasAs] = collection;
}
var updateScope = function(scope, index) {
scope[valueIdentifier] = value;
if (keyIdentifier) scope[keyIdentifier] = key;
scope.$index = index;
scope.$first = (index === 0);
scope.$last = (index === (arrayLength - 1));
scope.$middle = !(scope.$first || scope.$last);
// jshint bitwise: false
scope.$odd = !(scope.$even = (index&1) === 0);
// jshint bitwise: true
};
if (isArrayLike(collection)) {
collectionKeys = collection;
@@ -308,9 +281,9 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
trackByIdFn = trackByIdExpFn || trackByIdObjFn;
// if object, extract keys, sort them and use to determine order of iteration over obj props
collectionKeys = [];
for (var itemKey in collection) {
if (collection.hasOwnProperty(itemKey) && itemKey.charAt(0) != '$') {
collectionKeys.push(itemKey);
for (key in collection) {
if (collection.hasOwnProperty(key) && key.charAt(0) != '$') {
collectionKeys.push(key);
}
}
collectionKeys.sort();
@@ -346,10 +319,10 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
}
// remove existing items
for (var blockKey in lastBlockMap) {
for (key in lastBlockMap) {
// lastBlockMap is our own object so we don't need to use special hasOwnPropertyFn
if (lastBlockMap.hasOwnProperty(blockKey)) {
block = lastBlockMap[blockKey];
if (lastBlockMap.hasOwnProperty(key)) {
block = lastBlockMap[key];
elementsToRemove = getBlockElements(block.clone);
$animate.leave(elementsToRemove);
forEach(elementsToRemove, function(element) { element[NG_REMOVED] = true; });
@@ -367,6 +340,8 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
if (block.scope) {
// if we have already seen this object, then we need to reuse the
// associated scope/element
childScope = block.scope;
nextNode = previousNode;
do {
nextNode = nextNode.nextSibling;
@@ -377,20 +352,32 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
$animate.move(getBlockElements(block.clone), null, jqLite(previousNode));
}
previousNode = getBlockEnd(block);
updateScope(block.scope, index);
} else {
// new item which we don't know about
$transclude(function(clone, scope) {
block.scope = scope;
childScope = $scope.$new();
}
childScope[valueIdentifier] = value;
if (keyIdentifier) childScope[keyIdentifier] = key;
childScope.$index = index;
childScope.$first = (index === 0);
childScope.$last = (index === (arrayLength - 1));
childScope.$middle = !(childScope.$first || childScope.$last);
// jshint bitwise: false
childScope.$odd = !(childScope.$even = (index&1) === 0);
// jshint bitwise: true
if (!block.scope) {
$transclude(childScope, function(clone) {
clone[clone.length++] = document.createComment(' end ngRepeat: ' + expression + ' ');
$animate.enter(clone, null, jqLite(previousNode));
previousNode = clone;
block.scope = childScope;
// Note: We only need the first/last node of the cloned nodes.
// However, we need to keep the reference to the jqlite wrapper as it might be changed later
// by a directive with templateUrl when its template arrives.
block.clone = clone;
nextBlockMap[block.id] = block;
updateScope(block.scope, index);
});
}
}
+29 -39
View File
@@ -19,10 +19,15 @@
* <div ng-show="myValue" class="ng-hide"></div>
* ```
*
* When the ngShow expression evaluates to a falsy value then the ng-hide CSS class is added to the class
* attribute on the element causing it to become hidden. When truthy, the ng-hide CSS class is removed
* When the ngShow expression evaluates to false then the ng-hide CSS class is added to the class attribute
* on the element causing it to become hidden. When true, the ng-hide CSS class is removed
* from the element causing the element not to appear hidden.
*
* <div class="alert alert-warning">
* **Note:** Here is a list of values that ngShow will consider as a falsy value (case insensitive):<br />
* "f" / "0" / "false" / "no" / "n" / "[]"
* </div>
*
* ## Why is !important used?
*
* You may be wondering why !important is used for the .ng-hide CSS class. This is because the `.ng-hide` selector
@@ -42,7 +47,7 @@
*
* ```css
* .ng-hide {
* /&#42; this is just another form of hiding an element &#42;/
* //this is just another form of hiding an element
* display:block!important;
* position:absolute;
* top:-9999px;
@@ -64,15 +69,7 @@
* //a working example can be found at the bottom of this page
* //
* .my-element.ng-hide-add, .my-element.ng-hide-remove {
* /&#42; this is required as of 1.3x to properly
* apply all styling in a show/hide animation &#42;/
* transition:0s linear all;
* }
*
* .my-element.ng-hide-add-active,
* .my-element.ng-hide-remove-active {
* /&#42; the transition is defined in the active class &#42;/
* transition:1s linear all;
* transition:0.5s linear all;
* }
*
* .my-element.ng-hide-add { ... }
@@ -81,7 +78,7 @@
* .my-element.ng-hide-remove.ng-hide-remove-active { ... }
* ```
*
* Keep in mind that, as of AngularJS version 1.3.0-beta.11, there is no need to change the display
* Keep in mind that, as of AngularJS version 1.2.17 (and 1.3.0-beta.11), there is no need to change the display
* property to block during animation states--ngAnimate will handle the style toggling automatically for you.
*
* @animations
@@ -114,6 +111,8 @@
</file>
<file name="animations.css">
.animate-show {
-webkit-transition:all linear 0.5s;
transition:all linear 0.5s;
line-height:20px;
opacity:1;
padding:10px;
@@ -121,12 +120,6 @@
background:white;
}
.animate-show.ng-hide-add.ng-hide-add-active,
.animate-show.ng-hide-remove.ng-hide-remove-active {
-webkit-transition:all linear 0.5s;
transition:all linear 0.5s;
}
.animate-show.ng-hide {
line-height:0;
opacity:0;
@@ -156,14 +149,10 @@
</example>
*/
var ngShowDirective = ['$animate', function($animate) {
return {
restrict: 'A',
multiElement: true,
link: function(scope, element, attr) {
scope.$watch(attr.ngShow, function ngShowWatchAction(value){
$animate[value ? 'removeClass' : 'addClass'](element, 'ng-hide');
});
}
return function(scope, element, attr) {
scope.$watch(attr.ngShow, function ngShowWatchAction(value){
$animate[toBoolean(value) ? 'removeClass' : 'addClass'](element, 'ng-hide');
});
};
}];
@@ -187,10 +176,15 @@ var ngShowDirective = ['$animate', function($animate) {
* <div ng-hide="myValue"></div>
* ```
*
* When the ngHide expression evaluates to a truthy value then the .ng-hide CSS class is added to the class
* attribute on the element causing it to become hidden. When falsy, the ng-hide CSS class is removed
* When the ngHide expression evaluates to true then the .ng-hide CSS class is added to the class attribute
* on the element causing it to become hidden. When false, the ng-hide CSS class is removed
* from the element causing the element not to appear hidden.
*
* <div class="alert alert-warning">
* **Note:** Here is a list of values that ngHide will consider as a falsy value (case insensitive):<br />
* "f" / "0" / "false" / "no" / "n" / "[]"
* </div>
*
* ## Why is !important used?
*
* You may be wondering why !important is used for the .ng-hide CSS class. This is because the `.ng-hide` selector
@@ -210,7 +204,7 @@ var ngShowDirective = ['$animate', function($animate) {
*
* ```css
* .ng-hide {
* /&#42; this is just another form of hiding an element &#42;/
* //this is just another form of hiding an element
* display:block!important;
* position:absolute;
* top:-9999px;
@@ -240,7 +234,7 @@ var ngShowDirective = ['$animate', function($animate) {
* .my-element.ng-hide-remove.ng-hide-remove-active { ... }
* ```
*
* Keep in mind that, as of AngularJS version 1.3.0-beta.11, there is no need to change the display
* Keep in mind that, as of AngularJS version 1.2.17 (and 1.3.0-beta.11), there is no need to change the display
* property to block during animation states--ngAnimate will handle the style toggling automatically for you.
*
* @animations
@@ -311,13 +305,9 @@ var ngShowDirective = ['$animate', function($animate) {
</example>
*/
var ngHideDirective = ['$animate', function($animate) {
return {
restrict: 'A',
multiElement: true,
link: function(scope, element, attr) {
scope.$watch(attr.ngHide, function ngHideWatchAction(value){
$animate[value ? 'addClass' : 'removeClass'](element, 'ng-hide');
});
}
return function(scope, element, attr) {
scope.$watch(attr.ngHide, function ngHideWatchAction(value){
$animate[toBoolean(value) ? 'addClass' : 'removeClass'](element, 'ng-hide');
});
};
}];
+7 -10
View File
@@ -152,7 +152,7 @@ var ngSwitchDirective = ['$animate', function($animate) {
previousElements.length = 0;
for (i = 0, ii = selectedScopes.length; i < ii; ++i) {
var selected = getBlockElements(selectedElements[i].clone);
var selected = selectedElements[i];
selectedScopes[i].$destroy();
previousElements[i] = selected;
$animate.leave(selected, function() {
@@ -166,13 +166,12 @@ var ngSwitchDirective = ['$animate', function($animate) {
if ((selectedTranscludes = ngSwitchController.cases['!' + value] || ngSwitchController.cases['?'])) {
scope.$eval(attr.change);
forEach(selectedTranscludes, function(selectedTransclude) {
selectedTransclude.transclude(function(caseElement, selectedScope) {
selectedScopes.push(selectedScope);
var selectedScope = scope.$new();
selectedScopes.push(selectedScope);
selectedTransclude.transclude(selectedScope, function(caseElement) {
var anchor = selectedTransclude.element;
caseElement[caseElement.length++] = document.createComment(' end ngSwitchWhen: ');
var block = { clone: caseElement };
selectedElements.push(block);
selectedElements.push(caseElement);
$animate.enter(caseElement, anchor.parent(), anchor);
});
});
@@ -184,9 +183,8 @@ var ngSwitchDirective = ['$animate', function($animate) {
var ngSwitchWhenDirective = ngDirective({
transclude: 'element',
priority: 1200,
priority: 800,
require: '^ngSwitch',
multiElement: true,
link: function(scope, element, attrs, ctrl, $transclude) {
ctrl.cases['!' + attrs.ngSwitchWhen] = (ctrl.cases['!' + attrs.ngSwitchWhen] || []);
ctrl.cases['!' + attrs.ngSwitchWhen].push({ transclude: $transclude, element: element });
@@ -195,9 +193,8 @@ var ngSwitchWhenDirective = ngDirective({
var ngSwitchDefaultDirective = ngDirective({
transclude: 'element',
priority: 1200,
priority: 800,
require: '^ngSwitch',
multiElement: true,
link: function(scope, element, attr, ctrl, $transclude) {
ctrl.cases['?'] = (ctrl.cases['?'] || []);
ctrl.cases['?'].push({ transclude: $transclude, element: element });
+2 -3
View File
@@ -3,7 +3,7 @@
/**
* @ngdoc directive
* @name ngTransclude
* @restrict EAC
* @restrict AC
*
* @description
* Directive that marks the insertion point for the transcluded DOM of the nearest parent directive that uses transclusion.
@@ -24,7 +24,7 @@
scope: { title:'@' },
template: '<div style="border: 1px solid black;">' +
'<div style="background-color: gray">{{title}}</div>' +
'<ng-transclude></ng-transclude>' +
'<div ng-transclude></div>' +
'</div>'
};
})
@@ -55,7 +55,6 @@
*
*/
var ngTranscludeDirective = ngDirective({
restrict: 'EAC',
link: function($scope, $element, $attrs, controller, $transclude) {
if (!$transclude) {
throw minErr('ngTransclude')('orphan',
+5 -17
View File
@@ -135,11 +135,7 @@ var ngOptionsMinErr = minErr('ngOptions');
</example>
*/
var ngOptionsDirective = valueFn({
restrict: 'A',
terminal: true
});
var ngOptionsDirective = valueFn({ terminal: true });
// jshint maxlen: false
var selectDirective = ['$compile', '$parse', function($compile, $parse) {
//000011111111110000000000022222222220000000000000000000003333333333000000000000004444444444444440000000005555555555555550000000666666666666666000000000000000777777777700000000000000000008888888888
@@ -168,7 +164,7 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
};
self.addOption = function(value, element) {
self.addOption = function(value) {
assertNotHasOwnProperty(value, '"option value"');
optionsMap[value] = true;
@@ -176,12 +172,6 @@ var selectDirective = ['$compile', '$parse', function($compile, $parse) {
$element.val(value);
if (unknownOption.parent()) unknownOption.remove();
}
// Workaround for https://code.google.com/p/chromium/issues/detail?id=381459
// Adding an <option selected="selected"> element to a <select required="required"> should
// automatically select the new element
if (element[0].hasAttribute('selected')) {
element[0].selected = true;
}
};
@@ -644,13 +634,11 @@ var optionDirective = ['$interpolate', function($interpolate) {
if (interpolateFn) {
scope.$watch(interpolateFn, function interpolateWatchAction(newVal, oldVal) {
attr.$set('value', newVal);
if (oldVal !== newVal) {
selectCtrl.removeOption(oldVal);
}
selectCtrl.addOption(newVal, element);
if (newVal !== oldVal) selectCtrl.removeOption(oldVal);
selectCtrl.addOption(newVal);
});
} else {
selectCtrl.addOption(attr.value, element);
selectCtrl.addOption(attr.value);
}
element.on('$destroy', function() {
+1 -1
View File
@@ -2,5 +2,5 @@
var styleDirective = valueFn({
restrict: 'E',
terminal: false
terminal: true
});
+3 -33
View File
@@ -241,32 +241,6 @@ function timeZoneGetter(date) {
return paddedZone;
}
function getFirstThursdayOfYear(year) {
// 0 = index of January
var dayOfWeekOnFirst = (new Date(year, 0, 1)).getDay();
// 4 = index of Thursday (+1 to account for 1st = 5)
// 11 = index of *next* Thursday (+1 account for 1st = 12)
return new Date(year, 0, ((dayOfWeekOnFirst <= 4) ? 5 : 12) - dayOfWeekOnFirst);
}
function getThursdayThisWeek(datetime) {
return new Date(datetime.getFullYear(), datetime.getMonth(),
// 4 = index of Thursday
datetime.getDate() + (4 - datetime.getDay()));
}
function weekGetter(size) {
return function(date) {
var firstThurs = getFirstThursdayOfYear(date.getFullYear()),
thisThurs = getThursdayThisWeek(date);
var diff = +thisThurs - +firstThurs,
result = 1 + Math.round(diff / 6.048e8); // 6.048e8 ms per week
return padNumber(result, size);
};
}
function ampmGetter(date, formats) {
return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1];
}
@@ -295,12 +269,10 @@ var DATE_FORMATS = {
EEEE: dateStrGetter('Day'),
EEE: dateStrGetter('Day', true),
a: ampmGetter,
Z: timeZoneGetter,
ww: weekGetter(2),
w: weekGetter(1)
Z: timeZoneGetter
};
var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZEw']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z|w+))(.*)/,
var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,
NUMBER_STRING = /^\-?\d+$/;
/**
@@ -335,8 +307,6 @@ var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZEw']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d
* * `'.sss' or ',sss'`: Millisecond in second, padded (000-999)
* * `'a'`: am/pm marker
* * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-+1200)
* * `'ww'`: ISO-8601 week of year (00-53)
* * `'w'`: ISO-8601 week of year (0-53)
*
* `format` string can also be one of the following predefined
* {@link guide/i18n localizable formats}:
@@ -344,7 +314,7 @@ var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZEw']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d
* * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale
* (e.g. Sep 3, 2010 12:05:08 pm)
* * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US locale (e.g. 9/3/10 12:05 pm)
* * `'fullDate'`: equivalent to `'EEEE, MMMM d, y'` for en_US locale
* * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US locale
* (e.g. Friday, September 3, 2010)
* * `'longDate'`: equivalent to `'MMMM d, y'` for en_US locale (e.g. September 3, 2010)
* * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US locale (e.g. Sep 3, 2010)
+1 -1
View File
@@ -145,7 +145,7 @@ function orderByFilter($parse){
return 0;
}
function reverseComparator(comp, descending) {
return descending
return toBoolean(descending)
? function(a,b){return comp(b,a);}
: comp;
}
+73 -14
View File
@@ -149,6 +149,12 @@ function $HttpProvider() {
*/
var interceptorFactories = this.interceptors = [];
/**
* For historical reasons, response interceptors are ordered by the order in which
* they are applied to the response. (This is the opposite of interceptorFactories)
*/
var responseInterceptorFactories = this.responseInterceptors = [];
this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector',
function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) {
@@ -166,6 +172,27 @@ function $HttpProvider() {
? $injector.get(interceptorFactory) : $injector.invoke(interceptorFactory));
});
forEach(responseInterceptorFactories, function(interceptorFactory, index) {
var responseFn = isString(interceptorFactory)
? $injector.get(interceptorFactory)
: $injector.invoke(interceptorFactory);
/**
* Response interceptors go before "around" interceptors (no real reason, just
* had to pick one.) But they are already reversed, so we can't use unshift, hence
* the splice.
*/
reversedInterceptors.splice(index, 0, {
response: function(response) {
return responseFn($q.when(response));
},
responseError: function(response) {
return responseFn($q.reject(response));
}
});
});
/**
* @ngdoc service
* @kind function
@@ -419,6 +446,51 @@ function $HttpProvider() {
* });
* ```
*
* # Response interceptors (DEPRECATED)
*
* Before you start creating interceptors, be sure to understand the
* {@link ng.$q $q and deferred/promise APIs}.
*
* For purposes of global error handling, authentication or any kind of synchronous or
* asynchronous preprocessing of received responses, it is desirable to be able to intercept
* responses for http requests before they are handed over to the application code that
* initiated these requests. The response interceptors leverage the {@link ng.$q
* promise apis} to fulfil this need for both synchronous and asynchronous preprocessing.
*
* The interceptors are service factories that are registered with the $httpProvider by
* adding them to the `$httpProvider.responseInterceptors` array. The factory is called and
* injected with dependencies (if specified) and returns the interceptor — a function that
* takes a {@link ng.$q promise} and returns the original or a new promise.
*
* ```js
* // register the interceptor as a service
* $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {
* return function(promise) {
* return promise.then(function(response) {
* // do something on success
* return response;
* }, function(response) {
* // do something on error
* if (canRecover(response)) {
* return responseOrNewPromise
* }
* return $q.reject(response);
* });
* }
* });
*
* $httpProvider.responseInterceptors.push('myHttpInterceptor');
*
*
* // register the interceptor via an anonymous factory
* $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {
* return function(promise) {
* // same as above
* }
* });
* ```
*
*
* # Security Considerations
*
* When designing web applications, consider security threats from:
@@ -814,20 +886,7 @@ function $HttpProvider() {
* @param {Object=} config Optional configuration object
* @returns {HttpPromise} Future object
*/
/**
* @ngdoc method
* @name $http#patch
*
* @description
* Shortcut method to perform `PATCH` request.
*
* @param {string} url Relative or absolute URL specifying the destination of the request
* @param {*} data Request content
* @param {Object=} config Optional configuration object
* @returns {HttpPromise} Future object
*/
createShortMethodsWithData('post', 'put', 'patch');
createShortMethodsWithData('post', 'put');
/**
* @ngdoc property
+12
View File
@@ -196,6 +196,18 @@ function createHttpBackend($browser, createXhr, $browserDefer, callbacks, rawDoc
addEventListenerFn(script, "load", callback);
addEventListenerFn(script, "error", callback);
if (msie <= 8) {
script.onreadystatechange = function() {
if (isString(script.readyState) && /loaded|complete/.test(script.readyState)) {
script.onreadystatechange = null;
callback({
type: 'load'
});
}
};
}
rawDocument.body.appendChild(script);
return callback;
}
+62 -173
View File
@@ -81,13 +81,7 @@ function $InterpolateProvider() {
this.$get = ['$parse', '$exceptionHandler', '$sce', function($parse, $exceptionHandler, $sce) {
var startSymbolLength = startSymbol.length,
endSymbolLength = endSymbol.length,
escapedStartRegexp = new RegExp(startSymbol.replace(/./g, escape), 'g'),
escapedEndRegexp = new RegExp(endSymbol.replace(/./g, escape), 'g');
function escape(ch) {
return '\\\\\\' + ch;
}
endSymbolLength = endSymbol.length;
/**
* @ngdoc service
@@ -111,62 +105,6 @@ function $InterpolateProvider() {
* expect(exp({name:'Angular'}).toEqual('Hello ANGULAR!');
* ```
*
* `$interpolate` takes an optional fourth argument, `allOrNothing`. If `allOrNothing` is
* `true`, the interpolation function will return `undefined` unless all embedded expressions
* evaluate to a value other than `undefined`.
*
* ```js
* var $interpolate = ...; // injected
* var context = {greeting: 'Hello', name: undefined };
*
* // default "forgiving" mode
* var exp = $interpolate('{{greeting}} {{name}}!');
* expect(exp(context)).toEqual('Hello !');
*
* // "allOrNothing" mode
* exp = $interpolate('{{greeting}} {{name}}!', false, null, true);
* expect(exp(context)).toBeUndefined();
* context.name = 'Angular';
* expect(exp(context)).toEqual('Hello Angular!');
* ```
*
* `allOrNothing` is useful for interpolating URLs. `ngSrc` and `ngSrcset` use this behavior.
*
* ####Escaped Interpolation
* $interpolate provides a mechanism for escaping interpolation markers. Start and end markers
* can be escaped by preceding each of their characters with a REVERSE SOLIDUS U+005C (backslash).
* It will be rendered as a regular start/end marker, and will not be interpreted as an expression
* or binding.
*
* This enables web-servers to prevent script injection attacks and defacing attacks, to some
* degree, while also enabling code examples to work without relying on the
* {@link ng.directive:ngNonBindable ngNonBindable} directive.
*
* **For security purposes, it is strongly encouraged that web servers escape user-supplied data,
* replacing angle brackets (&lt;, &gt;) with &amp;lt; and &amp;gt; respectively, and replacing all
* interpolation start/end markers with their escaped counterparts.**
*
* Escaped interpolation markers are only replaced with the actual interpolation markers in rendered
* output when the $interpolate service processes the text. So, for HTML elements interpolated
* by {@link ng.$compile $compile}, or otherwise interpolated with the `mustHaveExpression` parameter
* set to `true`, the interpolated text must contain an unescaped interpolation expression. As such,
* this is typically useful only when user-data is used in rendering a template from the server, or
* when otherwise untrusted data is used by a directive.
*
* <example>
* <file name="index.html">
* <div ng-init="username='A user'">
* <p ng-init="apptitle='Escaping demo'">{{apptitle}}: \{\{ username = "defaced value"; \}\}
* </p>
* <p><strong>{{username}}</strong> attempts to inject code which will deface the
* application, but fails to accomplish their task, because the server has correctly
* escaped the interpolation start/end markers with REVERSE SOLIDUS U+005C (backslash)
* characters.</p>
* <p>Instead, the result of the attempted script injection is visible, and can be removed
* from the database by an administrator.</p>
* </div>
* </file>
* </example>
*
* @param {string} text The text with markup to interpolate.
* @param {boolean=} mustHaveExpression if set to true then the interpolation string must have
@@ -176,55 +114,43 @@ function $InterpolateProvider() {
* result through {@link ng.$sce#getTrusted $sce.getTrusted(interpolatedResult,
* trustedContext)} before returning it. Refer to the {@link ng.$sce $sce} service that
* provides Strict Contextual Escaping for details.
* @param {boolean=} allOrNothing if `true`, then the returned function returns undefined
* unless all embedded expressions evaluate to a value other than `undefined`.
* @returns {function(context)} an interpolation function which is used to compute the
* interpolated string. The function has these parameters:
*
* - `context`: evaluation context for all expressions embedded in the interpolated text
* * `context`: an object against which any expressions embedded in the strings are evaluated
* against.
*
*/
function $interpolate(text, mustHaveExpression, trustedContext, allOrNothing) {
allOrNothing = !!allOrNothing;
function $interpolate(text, mustHaveExpression, trustedContext) {
var startIndex,
endIndex,
index = 0,
separators = [],
expressions = [],
parseFns = [],
textLength = text.length,
parts = [],
length = text.length,
hasInterpolation = false,
hasText = false,
fn,
exp,
concat = [];
while(index < textLength) {
while(index < length) {
if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&
((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {
if (index !== startIndex) hasText = true;
separators.push(text.substring(index, startIndex));
exp = text.substring(startIndex + startSymbolLength, endIndex);
expressions.push(exp);
parseFns.push($parse(exp, parseStringifyInterceptor));
(index != startIndex) && parts.push(text.substring(index, startIndex));
parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));
fn.exp = exp;
index = endIndex + endSymbolLength;
hasInterpolation = true;
} else {
// we did not find an interpolation, so we have to add the remainder to the separators array
if (index !== textLength) {
hasText = true;
separators.push(text.substring(index));
}
break;
// we did not find anything, so we have to add the remainder to the parts array
(index != length) && parts.push(text.substring(index));
index = length;
}
}
forEach(separators, function(key, i) {
separators[i] = separators[i].
replace(escapedStartRegexp, startSymbol).
replace(escapedEndRegexp, endSymbol);
});
if (separators.length === expressions.length) {
separators.push('');
if (!(length = parts.length)) {
// we added, nothing, must have been an empty string.
parts.push('');
length = 1;
}
// Concatenating expressions makes it hard to reason about whether some combination of
@@ -233,95 +159,58 @@ function $InterpolateProvider() {
// that's used is assigned or constructed by some JS code somewhere that is more testable or
// make it obvious that you bound the value to some user controlled value. This helps reduce
// the load when auditing for XSS issues.
if (trustedContext && hasInterpolation && (hasText || expressions.length > 1)) {
if (trustedContext && parts.length > 1) {
throw $interpolateMinErr('noconcat',
"Error while interpolating: {0}\nStrict Contextual Escaping disallows " +
"interpolations that concatenate multiple expressions when a trusted value is " +
"required. See http://docs.angularjs.org/api/ng.$sce", text);
}
if (!mustHaveExpression || hasInterpolation) {
concat.length = separators.length + expressions.length;
var compute = function(values) {
for(var i = 0, ii = expressions.length; i < ii; i++) {
if (allOrNothing && isUndefined(values[i])) return;
concat[2*i] = separators[i];
concat[(2*i)+1] = values[i];
}
concat[2*ii] = separators[ii];
return concat.join('');
};
var getValue = function (value) {
return trustedContext ?
$sce.getTrusted(trustedContext, value) :
$sce.valueOf(value);
};
var stringify = function (value) {
if (value == null) { // null || undefined
return '';
}
switch (typeof value) {
case 'string': {
break;
}
case 'number': {
value = '' + value;
break;
}
default: {
value = toJson(value);
}
}
return value;
};
return extend(function interpolationFn(context) {
var i = 0;
var ii = expressions.length;
var values = new Array(ii);
try {
for (; i < ii; i++) {
values[i] = parseFns[i](context);
if (!mustHaveExpression || hasInterpolation) {
concat.length = length;
fn = function(context) {
try {
for(var i = 0, ii = length, part; i<ii; i++) {
if (typeof (part = parts[i]) == 'function') {
part = part(context);
if (trustedContext) {
part = $sce.getTrusted(trustedContext, part);
} else {
part = $sce.valueOf(part);
}
if (part == null) { // null || undefined
part = '';
} else {
switch (typeof part) {
case 'string':
{
break;
}
case 'number':
{
part = '' + part;
break;
}
default:
{
part = toJson(part);
}
}
}
}
return compute(values);
} catch(err) {
var newErr = $interpolateMinErr('interr', "Can't interpolate: {0}\n{1}", text,
err.toString());
$exceptionHandler(newErr);
concat[i] = part;
}
}, {
// all of these properties are undocumented for now
exp: text, //just for compatibility with regular watchers created via $watch
separators: separators,
expressions: expressions,
$$watchDelegate: function (scope, listener, objectEquality, deregisterNotifier) {
var lastValue;
return scope.$watchGroup(parseFns, function interpolateFnWatcher(values, oldValues) {
var currValue = compute(values);
if (isFunction(listener)) {
listener.call(this, currValue, values !== oldValues ? lastValue : currValue, scope);
}
lastValue = currValue;
}, objectEquality, deregisterNotifier);
return concat.join('');
}
});
}
function parseStringifyInterceptor(value) {
try {
return stringify(getValue(value));
} catch(err) {
var newErr = $interpolateMinErr('interr', "Can't interpolate: {0}\n{1}", text,
err.toString());
$exceptionHandler(newErr);
}
catch(err) {
var newErr = $interpolateMinErr('interr', "Can't interpolate: {0}\n{1}", text,
err.toString());
$exceptionHandler(newErr);
}
};
fn.exp = text;
fn.parts = parts;
return fn;
}
}
+6 -6
View File
@@ -2,8 +2,8 @@
function $IntervalProvider() {
this.$get = ['$rootScope', '$window', '$q', '$$q',
function($rootScope, $window, $q, $$q) {
this.$get = ['$rootScope', '$window', '$q',
function($rootScope, $window, $q) {
var intervals = {};
@@ -108,7 +108,7 @@ function $IntervalProvider() {
*
* // listen on DOM destroy (removal) event, and cancel the next UI update
* // to prevent updating time after the DOM element was removed.
* element.on('$destroy', function() {
* element.bind('$destroy', function() {
* $interval.cancel(stopTime);
* });
* }
@@ -134,10 +134,10 @@ function $IntervalProvider() {
function interval(fn, delay, count, invokeApply) {
var setInterval = $window.setInterval,
clearInterval = $window.clearInterval,
deferred = $q.defer(),
promise = deferred.promise,
iteration = 0,
skipApply = (isDefined(invokeApply) && !invokeApply),
deferred = (skipApply ? $$q : $q).defer(),
promise = deferred.promise;
skipApply = (isDefined(invokeApply) && !invokeApply);
count = isDefined(count) ? count : 0;
+1 -1
View File
@@ -646,7 +646,7 @@ function $LocationProvider(){
var elm = jqLite(event.target);
// traverse the DOM up to find first A tag
while (nodeName_(elm[0]) !== 'a') {
while (lowercase(elm[0].nodeName) !== 'a') {
// ignore rewriting if no A tag (reached root element, or no parent - removed from document)
if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;
}
+279 -147
View File
@@ -1,6 +1,8 @@
'use strict';
var $parseMinErr = minErr('$parse');
var promiseWarningCache = {};
var promiseWarning;
// Sandboxing Angular Expressions
// ------------------------------
@@ -43,7 +45,7 @@ function ensureSafeObject(obj, fullExpression) {
'Referencing Function in Angular expressions is disallowed! Expression: {0}',
fullExpression);
} else if (// isWindow(obj)
obj.window === obj) {
obj.document && obj.location && obj.alert && obj.setInterval) {
throw $parseMinErr('isecwindow',
'Referencing the Window in Angular expressions is disallowed! Expression: {0}',
fullExpression);
@@ -72,7 +74,7 @@ function ensureSafeFunction(obj, fullExpression) {
throw $parseMinErr('isecfn',
'Referencing Function in Angular expressions is disallowed! Expression: {0}',
fullExpression);
} else if (obj === CALL || obj === APPLY || obj === BIND) {
} else if (obj === CALL || obj === APPLY || (BIND && obj === BIND)) {
throw $parseMinErr('isecff',
'Referencing call, apply or bind in Angular expressions is disallowed! Expression: {0}',
fullExpression);
@@ -138,8 +140,11 @@ Lexer.prototype = {
lex: function (text) {
this.text = text;
this.index = 0;
this.ch = undefined;
this.lastCh = ':'; // can start regexp
this.tokens = [];
while (this.index < this.text.length) {
@@ -158,6 +163,7 @@ Lexer.prototype = {
this.index++;
} else if (this.isWhitespace(this.ch)) {
this.index++;
continue;
} else {
var ch2 = this.ch + this.peek();
var ch3 = ch2 + this.peek(2);
@@ -181,6 +187,7 @@ Lexer.prototype = {
this.throwError('Unexpected next character ', this.index, this.index + 1);
}
}
this.lastCh = this.ch;
}
return this.tokens;
},
@@ -189,6 +196,10 @@ Lexer.prototype = {
return chars.indexOf(this.ch) !== -1;
},
was: function(chars) {
return chars.indexOf(this.lastCh) !== -1;
},
peek: function(i) {
var num = i || 1;
return (this.index + num < this.text.length) ? this.text.charAt(this.index + num) : false;
@@ -252,6 +263,7 @@ Lexer.prototype = {
this.tokens.push({
index: start,
text: number,
literal: true,
constant: true,
fn: function() { return number; }
});
@@ -304,6 +316,7 @@ Lexer.prototype = {
// OPERATORS is our own object so we don't need to use special hasOwnPropertyFn
if (OPERATORS.hasOwnProperty(ident)) {
token.fn = OPERATORS[ident];
token.literal = true;
token.constant = true;
} else {
var getter = getterFn(ident, this.options, this.text);
@@ -311,7 +324,7 @@ Lexer.prototype = {
return (getter(self, locals));
}, {
assign: function(self, value) {
return setter(self, ident, value, parser.text);
return setter(self, ident, value, parser.text, parser.options);
}
});
}
@@ -320,7 +333,7 @@ Lexer.prototype = {
if (methodName) {
this.tokens.push({
index: lastDot,
index:lastDot,
text: '.'
});
this.tokens.push({
@@ -359,6 +372,7 @@ Lexer.prototype = {
index: start,
text: rawString,
string: string,
literal: true,
constant: true,
fn: function() { return string; }
});
@@ -393,6 +407,7 @@ Parser.prototype = {
parse: function (text) {
this.text = text;
this.tokens = this.lexer.lex(text);
var value = this.statements();
@@ -422,10 +437,8 @@ Parser.prototype = {
if (!primary) {
this.throwError('not a primary expression', token);
}
if (token.constant) {
primary.constant = true;
primary.literal = true;
}
primary.literal = !!token.literal;
primary.constant = !!token.constant;
}
var next, context;
@@ -549,17 +562,21 @@ Parser.prototype = {
var token = this.expect();
var fn = this.$filter(token.text);
var argsFn = [];
while(this.expect(':')) {
argsFn.push(this.expression());
}
return valueFn(fnInvoke);
function fnInvoke(self, locals, input) {
var args = [input];
for (var i = 0; i < argsFn.length; i++) {
args.push(argsFn[i](self, locals));
while (true) {
if ((token = this.expect(':'))) {
argsFn.push(this.expression());
} else {
var fnInvoke = function(self, locals, input) {
var args = [input];
for (var i = 0; i < argsFn.length; i++) {
args.push(argsFn[i](self, locals));
}
return fn.apply(self, args);
};
return function() {
return fnInvoke;
};
}
return fn.apply(self, args);
}
},
@@ -681,7 +698,7 @@ Parser.prototype = {
assign: function(scope, value, locals) {
var o = object(scope, locals);
if (!o) object.assign(scope, o = {});
return setter(o, field, value, parser.text);
return setter(o, field, value, parser.text, parser.options);
}
});
},
@@ -695,11 +712,19 @@ Parser.prototype = {
return extend(function(self, locals) {
var o = obj(self, locals),
i = indexFn(self, locals),
v;
v, p;
ensureSafeMemberName(i, parser.text);
if (!o) return undefined;
v = ensureSafeObject(o[i], parser.text);
if (v && v.then && parser.options.unwrapPromises) {
p = v;
if (!('$$v' in v)) {
p.$$v = undefined;
p.then(function(val) { p.$$v = val; });
}
v = v.$$v;
}
return v;
}, {
assign: function(self, value, locals) {
@@ -815,7 +840,9 @@ Parser.prototype = {
// Parser helper functions
//////////////////////////////////////////////////
function setter(obj, path, setValue, fullExp) {
function setter(obj, path, setValue, fullExp, options) {
//needed?
options = options || {};
var element = path.split('.'), key;
for (var i = 0; element.length > 1; i++) {
@@ -826,6 +853,18 @@ function setter(obj, path, setValue, fullExp) {
obj[key] = propertyObj;
}
obj = propertyObj;
if (obj.then && options.unwrapPromises) {
promiseWarning(fullExp);
if (!("$$v" in obj)) {
(function(promise) {
promise.then(function(val) { promise.$$v = val; }); }
)(obj);
}
if (obj.$$v === undefined) {
obj.$$v = {};
}
obj = obj.$$v;
}
}
key = ensureSafeMemberName(element.shift(), fullExp);
ensureSafeObject(obj, fullExp);
@@ -841,37 +880,108 @@ var getterFnCache = {};
* - http://jsperf.com/angularjs-parse-getter/4
* - http://jsperf.com/path-evaluation-simplified/7
*/
function cspSafeGetterFn(key0, key1, key2, key3, key4, fullExp) {
function cspSafeGetterFn(key0, key1, key2, key3, key4, fullExp, options) {
ensureSafeMemberName(key0, fullExp);
ensureSafeMemberName(key1, fullExp);
ensureSafeMemberName(key2, fullExp);
ensureSafeMemberName(key3, fullExp);
ensureSafeMemberName(key4, fullExp);
return function cspSafeGetter(scope, locals) {
var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope;
return !options.unwrapPromises
? function cspSafeGetter(scope, locals) {
var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope;
if (pathVal == null) return pathVal;
pathVal = pathVal[key0];
if (pathVal == null) return pathVal;
pathVal = pathVal[key0];
if (!key1) return pathVal;
if (pathVal == null) return undefined;
pathVal = pathVal[key1];
if (!key1) return pathVal;
if (pathVal == null) return undefined;
pathVal = pathVal[key1];
if (!key2) return pathVal;
if (pathVal == null) return undefined;
pathVal = pathVal[key2];
if (!key2) return pathVal;
if (pathVal == null) return undefined;
pathVal = pathVal[key2];
if (!key3) return pathVal;
if (pathVal == null) return undefined;
pathVal = pathVal[key3];
if (!key3) return pathVal;
if (pathVal == null) return undefined;
pathVal = pathVal[key3];
if (!key4) return pathVal;
if (pathVal == null) return undefined;
pathVal = pathVal[key4];
if (!key4) return pathVal;
if (pathVal == null) return undefined;
pathVal = pathVal[key4];
return pathVal;
};
return pathVal;
}
: function cspSafePromiseEnabledGetter(scope, locals) {
var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope,
promise;
if (pathVal == null) return pathVal;
pathVal = pathVal[key0];
if (pathVal && pathVal.then) {
promiseWarning(fullExp);
if (!("$$v" in pathVal)) {
promise = pathVal;
promise.$$v = undefined;
promise.then(function(val) { promise.$$v = val; });
}
pathVal = pathVal.$$v;
}
if (!key1) return pathVal;
if (pathVal == null) return undefined;
pathVal = pathVal[key1];
if (pathVal && pathVal.then) {
promiseWarning(fullExp);
if (!("$$v" in pathVal)) {
promise = pathVal;
promise.$$v = undefined;
promise.then(function(val) { promise.$$v = val; });
}
pathVal = pathVal.$$v;
}
if (!key2) return pathVal;
if (pathVal == null) return undefined;
pathVal = pathVal[key2];
if (pathVal && pathVal.then) {
promiseWarning(fullExp);
if (!("$$v" in pathVal)) {
promise = pathVal;
promise.$$v = undefined;
promise.then(function(val) { promise.$$v = val; });
}
pathVal = pathVal.$$v;
}
if (!key3) return pathVal;
if (pathVal == null) return undefined;
pathVal = pathVal[key3];
if (pathVal && pathVal.then) {
promiseWarning(fullExp);
if (!("$$v" in pathVal)) {
promise = pathVal;
promise.$$v = undefined;
promise.then(function(val) { promise.$$v = val; });
}
pathVal = pathVal.$$v;
}
if (!key4) return pathVal;
if (pathVal == null) return undefined;
pathVal = pathVal[key4];
if (pathVal && pathVal.then) {
promiseWarning(fullExp);
if (!("$$v" in pathVal)) {
promise = pathVal;
promise.$$v = undefined;
promise.then(function(val) { promise.$$v = val; });
}
pathVal = pathVal.$$v;
}
return pathVal;
};
}
function getterFn(path, options, fullExp) {
@@ -889,13 +999,14 @@ function getterFn(path, options, fullExp) {
// http://jsperf.com/angularjs-parse-getter/6
if (options.csp) {
if (pathKeysLength < 6) {
fn = cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4], fullExp);
fn = cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4], fullExp,
options);
} else {
fn = function(scope, locals) {
var i = 0, val;
do {
val = cspSafeGetterFn(pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++],
pathKeys[i++], fullExp)(scope, locals);
pathKeys[i++], fullExp, options)(scope, locals);
locals = undefined; // clear after first iteration
scope = val;
@@ -912,15 +1023,28 @@ function getterFn(path, options, fullExp) {
// we simply dereference 's' on any .dot notation
? 's'
// but if we are first then we check locals first, and if so read it first
: '((k&&k.hasOwnProperty("' + key + '"))?k:s)') + '.' + key + ';\n';
: '((k&&k.hasOwnProperty("' + key + '"))?k:s)') + '["' + key + '"]' + ';\n' +
(options.unwrapPromises
? 'if (s && s.then) {\n' +
' pw("' + fullExp.replace(/(["\r\n])/g, '\\$1') + '");\n' +
' if (!("$$v" in s)) {\n' +
' p=s;\n' +
' p.$$v = undefined;\n' +
' p.then(function(v) {p.$$v=v;});\n' +
'}\n' +
' s=s.$$v\n' +
'}\n'
: '');
});
code += 'return s;';
/* jshint -W054 */
var evaledFnGetter = new Function('s', 'k', code); // s=scope, k=locals
var evaledFnGetter = new Function('s', 'k', 'pw', code); // s=scope, k=locals, pw=promiseWarning
/* jshint +W054 */
evaledFnGetter.toString = valueFn(code);
fn = evaledFnGetter;
fn = options.unwrapPromises ? function(scope, locals) {
return evaledFnGetter(scope, locals, promiseWarning);
} : evaledFnGetter;
}
// Only cache the value if it's not going to mess up the cache object
@@ -987,123 +1111,131 @@ function $ParseProvider() {
var cache = {};
var $parseOptions = {
csp: false
csp: false,
unwrapPromises: false,
logPromiseWarnings: true
};
this.$get = ['$filter', '$sniffer', function($filter, $sniffer) {
/**
* @deprecated Promise unwrapping via $parse is deprecated and will be removed in the future.
*
* @ngdoc method
* @name $parseProvider#unwrapPromises
* @description
*
* **This feature is deprecated, see deprecation notes below for more info**
*
* If set to true (default is false), $parse will unwrap promises automatically when a promise is
* found at any part of the expression. In other words, if set to true, the expression will always
* result in a non-promise value.
*
* While the promise is unresolved, it's treated as undefined, but once resolved and fulfilled,
* the fulfillment value is used in place of the promise while evaluating the expression.
*
* **Deprecation notice**
*
* This is a feature that didn't prove to be wildly useful or popular, primarily because of the
* dichotomy between data access in templates (accessed as raw values) and controller code
* (accessed as promises).
*
* In most code we ended up resolving promises manually in controllers anyway and thus unifying
* the model access there.
*
* Other downsides of automatic promise unwrapping:
*
* - when building components it's often desirable to receive the raw promises
* - adds complexity and slows down expression evaluation
* - makes expression code pre-generation unattractive due to the amount of code that needs to be
* generated
* - makes IDE auto-completion and tool support hard
*
* **Warning Logs**
*
* If the unwrapping is enabled, Angular will log a warning about each expression that unwraps a
* promise (to reduce the noise, each expression is logged only once). To disable this logging use
* `$parseProvider.logPromiseWarnings(false)` api.
*
*
* @param {boolean=} value New value.
* @returns {boolean|self} Returns the current setting when used as getter and self if used as
* setter.
*/
this.unwrapPromises = function(value) {
if (isDefined(value)) {
$parseOptions.unwrapPromises = !!value;
return this;
} else {
return $parseOptions.unwrapPromises;
}
};
/**
* @deprecated Promise unwrapping via $parse is deprecated and will be removed in the future.
*
* @ngdoc method
* @name $parseProvider#logPromiseWarnings
* @description
*
* Controls whether Angular should log a warning on any encounter of a promise in an expression.
*
* The default is set to `true`.
*
* This setting applies only if `$parseProvider.unwrapPromises` setting is set to true as well.
*
* @param {boolean=} value New value.
* @returns {boolean|self} Returns the current setting when used as getter and self if used as
* setter.
*/
this.logPromiseWarnings = function(value) {
if (isDefined(value)) {
$parseOptions.logPromiseWarnings = value;
return this;
} else {
return $parseOptions.logPromiseWarnings;
}
};
this.$get = ['$filter', '$sniffer', '$log', function($filter, $sniffer, $log) {
$parseOptions.csp = $sniffer.csp;
return function(exp, interceptorFn) {
var parsedExpression, oneTime,
cacheKey = (exp = trim(exp));
promiseWarning = function promiseWarningFn(fullExp) {
if (!$parseOptions.logPromiseWarnings || promiseWarningCache.hasOwnProperty(fullExp)) return;
promiseWarningCache[fullExp] = true;
$log.warn('[$parse] Promise found in the expression `' + fullExp + '`. ' +
'Automatic unwrapping of promises in Angular expressions is deprecated.');
};
return function(exp) {
var parsedExpression;
switch (typeof exp) {
case 'string':
if (cache.hasOwnProperty(cacheKey)) {
parsedExpression = cache[cacheKey];
} else {
if (exp.charAt(0) === ':' && exp.charAt(1) === ':') {
oneTime = true;
exp = exp.substring(2);
}
var lexer = new Lexer($parseOptions);
var parser = new Parser(lexer, $filter, $parseOptions);
parsedExpression = parser.parse(exp);
if (parsedExpression.constant) {
parsedExpression.$$watchDelegate = constantWatch;
} else if (oneTime) {
parsedExpression.$$watchDelegate = parsedExpression.literal ?
oneTimeLiteralWatch : oneTimeWatch;
}
if (cacheKey !== 'hasOwnProperty') {
// Only cache the value if it's not going to mess up the cache object
// This is more performant that using Object.prototype.hasOwnProperty.call
cache[cacheKey] = parsedExpression;
}
if (cache.hasOwnProperty(exp)) {
return cache[exp];
}
return addInterceptor(parsedExpression, interceptorFn);
var lexer = new Lexer($parseOptions);
var parser = new Parser(lexer, $filter, $parseOptions);
parsedExpression = parser.parse(exp);
if (exp !== 'hasOwnProperty') {
// Only cache the value if it's not going to mess up the cache object
// This is more performant that using Object.prototype.hasOwnProperty.call
cache[exp] = parsedExpression;
}
return parsedExpression;
case 'function':
return addInterceptor(exp, interceptorFn);
return exp;
default:
return addInterceptor(noop, interceptorFn);
return noop;
}
};
function oneTimeWatch(scope, listener, objectEquality, deregisterNotifier, parsedExpression) {
var unwatch, lastValue;
return unwatch = scope.$watch(function oneTimeWatch(scope) {
return parsedExpression(scope);
}, function oneTimeListener(value, old, scope) {
lastValue = value;
if (isFunction(listener)) {
listener.apply(this, arguments);
}
if (isDefined(value)) {
scope.$$postDigest(function () {
if (isDefined(lastValue)) {
unwatch();
}
});
}
}, objectEquality, deregisterNotifier);
}
function oneTimeLiteralWatch(scope, listener, objectEquality, deregisterNotifier, parsedExpression) {
var unwatch;
return unwatch = scope.$watch(function oneTimeWatch(scope) {
return parsedExpression(scope);
}, function oneTimeListener(value, old, scope) {
if (isFunction(listener)) {
listener.call(this, value, old, scope);
}
if (isAllDefined(value)) {
scope.$$postDigest(function () {
if(isAllDefined(value)) unwatch();
});
}
}, objectEquality);
function isAllDefined(value) {
var allDefined = true;
forEach(value, function (val) {
if (!isDefined(val)) allDefined = false;
});
return allDefined;
}
}
function constantWatch(scope, listener, objectEquality, deregisterNotifier, parsedExpression) {
var unwatch;
return unwatch = scope.$watch(function constantWatch(scope) {
return parsedExpression(scope);
}, function constantListener(value, old, scope) {
if (isFunction(listener)) {
listener.apply(this, arguments);
}
unwatch();
}, objectEquality, deregisterNotifier);
}
function addInterceptor(parsedExpression, interceptorFn) {
if (isFunction(interceptorFn)) {
var fn = function interceptedExpression(scope, locals) {
var value = parsedExpression(scope, locals);
var result = interceptorFn(value, scope, locals);
// we only return the interceptor's result if the
// initial value is defined (for bind-once)
return isDefined(value) ? result : value;
};
fn.$$watchDelegate = parsedExpression.$$watchDelegate;
return fn;
} else {
return parsedExpression;
}
}
}];
}
+126 -211
View File
@@ -8,46 +8,6 @@
* @description
* A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q).
*
* $q can be used in two fashions --- One, which is more similar to Kris Kowal's Q or jQuery's Deferred
* implementations, the other resembles ES6 promises to some degree.
*
* # $q constructor
*
* The streamlined ES6 style promise is essentially just using $q as a constructor which takes a `resolver`
* function as the first argument). This is similar to the native Promise implementation from ES6 Harmony,
* see [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise).
*
* While the constructor-style use is supported, not all of the supporting methods from Harmony promises are
* available yet.
*
* It can be used like so:
*
* ```js
* return $q(function(resolve, reject) {
* // perform some asynchronous operation, resolve or reject the promise when appropriate.
* setInterval(function() {
* if (pollStatus > 0) {
* resolve(polledValue);
* } else if (pollStatus < 0) {
* reject(polledValue);
* } else {
* pollStatus = pollAgain(function(value) {
* polledValue = value;
* });
* }
* }, 10000);
* }).
* then(function(value) {
* // handle success
* }, function(reason) {
* // handle failure
* });
* ```
*
* Note, progress/notify callbacks are not currently supported via the ES6-style interface.
*
* However, the more traditional CommonJS style usage is still available, and documented below.
*
* [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an
* interface for interacting with an object that represents the result of an action that is
* performed asynchronously, and may or may not be finished at any given point in time.
@@ -94,6 +54,7 @@
* For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the
* section on serial or parallel joining of promises.
*
*
* # The Deferred API
*
* A new instance of deferred is constructed by calling `$q.defer()`.
@@ -202,12 +163,6 @@
* expect(resolvedValue).toEqual(123);
* }));
* ```
*
* @param {function(function, function)} resolver Function which is responsible for resolving or
* rejecting the newly created promise. The first parameteter is a function which resolves the
* promise, the second parameter is a function which rejects the promise.
*
* @returns {Promise} The newly created promise.
*/
function $QProvider() {
@@ -218,13 +173,6 @@ function $QProvider() {
}];
}
function $$QProvider() {
this.$get = ['$browser', '$exceptionHandler', function($browser, $exceptionHandler) {
return qFactory(function(callback) {
$browser.defer(callback);
}, $exceptionHandler);
}];
}
/**
* Constructs a promise manager.
@@ -247,122 +195,143 @@ function qFactory(nextTick, exceptionHandler) {
* @returns {Deferred} Returns a new instance of deferred.
*/
var defer = function() {
return new Deferred();
};
var pending = [],
value, deferred;
function Promise () {
this.$$pending = [];
}
deferred = {
Promise.prototype = {
then: function(callback, errback, progressback) {
var result = new Deferred();
resolve: function(val) {
if (pending) {
var callbacks = pending;
pending = undefined;
value = ref(val);
var wrappedCallback = function(value) {
try {
result.resolve((isFunction(callback) ? callback : defaultCallback)(value));
} catch(e) {
result.reject(e);
exceptionHandler(e);
if (callbacks.length) {
nextTick(function() {
var callback;
for (var i = 0, ii = callbacks.length; i < ii; i++) {
callback = callbacks[i];
value.then(callback[0], callback[1], callback[2]);
}
});
}
}
};
},
var wrappedErrback = function(reason) {
try {
result.resolve((isFunction(errback) ? errback : defaultErrback)(reason));
} catch(e) {
result.reject(e);
exceptionHandler(e);
reject: function(reason) {
deferred.resolve(createInternalRejectedPromise(reason));
},
notify: function(progress) {
if (pending) {
var callbacks = pending;
if (pending.length) {
nextTick(function() {
var callback;
for (var i = 0, ii = callbacks.length; i < ii; i++) {
callback = callbacks[i];
callback[2](progress);
}
});
}
}
};
},
var wrappedProgressback = function(progress) {
try {
result.notify((isFunction(progressback) ? progressback : defaultCallback)(progress));
} catch(e) {
exceptionHandler(e);
}
};
if (this.$$pending) {
this.$$pending.push([wrappedCallback, wrappedErrback, wrappedProgressback]);
} else {
this.$$value.then(wrappedCallback, wrappedErrback, wrappedProgressback);
}
promise: {
then: function(callback, errback, progressback) {
var result = defer();
return result.promise;
},
"catch": function(callback) {
return this.then(null, callback);
},
"finally": function(callback) {
return this.then(function(value) {
return handleCallback(value, true, callback);
}, function(error) {
return handleCallback(error, false, callback);
});
}
};
//Faster, more basic than angular.bind http://jsperf.com/angular-bind-vs-custom-vs-native
function simpleBind(context, fn) {
return function(value) {
fn.call(context, value);
};
}
function Deferred () {
this.promise = new Promise();
//Necessary to support unbound execution :/
this.resolve = simpleBind(this, this.resolve);
this.reject = simpleBind(this, this.reject);
this.notify = simpleBind(this, this.notify);
}
Deferred.prototype = {
resolve: function(val) {
if (this.promise.$$pending) {
var callbacks = this.promise.$$pending;
this.promise.$$pending = undefined;
this.promise.$$value = ref(val);
if (callbacks.length) {
nextTick(simpleBind(this, function() {
var callback;
for (var i = 0, ii = callbacks.length; i < ii; i++) {
callback = callbacks[i];
this.promise.$$value.then(callback[0], callback[1], callback[2]);
var wrappedCallback = function(value) {
try {
result.resolve((isFunction(callback) ? callback : defaultCallback)(value));
} catch(e) {
result.reject(e);
exceptionHandler(e);
}
}));
}
}
},
reject: function(reason) {
this.resolve(createInternalRejectedPromise(reason));
},
notify: function(progress) {
if (this.promise.$$pending) {
var callbacks = this.promise.$$pending;
};
if (this.promise.$$pending.length) {
nextTick(function() {
var callback;
for (var i = 0, ii = callbacks.length; i < ii; i++) {
callback = callbacks[i];
callback[2](progress);
var wrappedErrback = function(reason) {
try {
result.resolve((isFunction(errback) ? errback : defaultErrback)(reason));
} catch(e) {
result.reject(e);
exceptionHandler(e);
}
};
var wrappedProgressback = function(progress) {
try {
result.notify((isFunction(progressback) ? progressback : defaultCallback)(progress));
} catch(e) {
exceptionHandler(e);
}
};
if (pending) {
pending.push([wrappedCallback, wrappedErrback, wrappedProgressback]);
} else {
value.then(wrappedCallback, wrappedErrback, wrappedProgressback);
}
return result.promise;
},
"catch": function(callback) {
return this.then(null, callback);
},
"finally": function(callback) {
function makePromise(value, resolved) {
var result = defer();
if (resolved) {
result.resolve(value);
} else {
result.reject(value);
}
return result.promise;
}
function handleCallback(value, isResolved) {
var callbackOutput = null;
try {
callbackOutput = (callback ||defaultCallback)();
} catch(e) {
return makePromise(e, false);
}
if (isPromiseLike(callbackOutput)) {
return callbackOutput.then(function() {
return makePromise(value, isResolved);
}, function(error) {
return makePromise(error, false);
});
} else {
return makePromise(value, isResolved);
}
}
return this.then(function(value) {
return handleCallback(value, true);
}, function(error) {
return handleCallback(error, false);
});
}
}
}
};
return deferred;
};
var ref = function(value) {
if (isPromiseLike(value)) return value;
return {
then: function(callback) {
var result = new Deferred();
var result = defer();
nextTick(function() {
result.resolve(callback(value));
});
@@ -409,43 +378,15 @@ function qFactory(nextTick, exceptionHandler) {
* @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`.
*/
var reject = function(reason) {
var result = new Deferred();
var result = defer();
result.reject(reason);
return result.promise;
};
var makePromise = function makePromise(value, resolved) {
var result = new Deferred();
if (resolved) {
result.resolve(value);
} else {
result.reject(value);
}
return result.promise;
};
var handleCallback = function handleCallback(value, isResolved, callback) {
var callbackOutput = null;
try {
callbackOutput = (callback ||defaultCallback)();
} catch(e) {
return makePromise(e, false);
}
if (isPromiseLike(callbackOutput)) {
return callbackOutput.then(function() {
return makePromise(value, isResolved);
}, function(error) {
return makePromise(error, false);
});
} else {
return makePromise(value, isResolved);
}
};
var createInternalRejectedPromise = function(reason) {
return {
then: function(callback, errback) {
var result = new Deferred();
var result = defer();
nextTick(function() {
try {
result.resolve((isFunction(errback) ? errback : defaultErrback)(reason));
@@ -474,7 +415,7 @@ function qFactory(nextTick, exceptionHandler) {
* @returns {Promise} Returns a promise of the passed value or promise
*/
var when = function(value, callback, errback, progressback) {
var result = new Deferred(),
var result = defer(),
done;
var wrappedCallback = function(value) {
@@ -548,7 +489,7 @@ function qFactory(nextTick, exceptionHandler) {
* with the same rejection value.
*/
function all(promises) {
var deferred = new Deferred(),
var deferred = defer(),
counter = 0,
results = isArray(promises) ? [] : {};
@@ -571,36 +512,10 @@ function qFactory(nextTick, exceptionHandler) {
return deferred.promise;
}
var $Q = function Q(resolver) {
if (!isFunction(resolver)) {
// TODO(@caitp): minErr this
throw new TypeError('Expected resolverFn');
}
if (!(this instanceof Q)) {
// More useful when $Q is the Promise itself.
return new Q(resolver);
}
var deferred = new Deferred();
function resolveFn(value) {
deferred.resolve(value);
}
function rejectFn(reason) {
deferred.reject(reason);
}
resolver(resolveFn, rejectFn);
return deferred.promise;
return {
defer: defer,
reject: reject,
when: when,
all: all
};
$Q.defer = defer;
$Q.reject = reject;
$Q.when = when;
$Q.all = all;
return $Q;
}
+31 -105
View File
@@ -248,6 +248,7 @@ function $RootScopeProvider(){
* can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the
* listener was called due to initialization.
*
* The example below contains an illustration of using a function as your $watch listener
*
*
* # Example
@@ -277,14 +278,14 @@ function $RootScopeProvider(){
// Using a function as a watchExpression
// Using a listener function
var food;
scope.foodCounter = 0;
expect(scope.foodCounter).toEqual(0);
scope.$watch(
// This function returns the value being watched. It is called for each turn of the $digest loop
// This is the listener function
function() { return food; },
// This is the change listener, called when the value returned from the above function changes
// This is the change handler
function(newValue, oldValue) {
if ( newValue !== oldValue ) {
// Only increment the counter if the value changed
@@ -314,25 +315,20 @@ function $RootScopeProvider(){
*
* - `string`: Evaluated as {@link guide/expression expression}
* - `function(scope)`: called with current `scope` as a parameter.
* @param {function(newVal, oldVal, scope)} listener Callback called whenever the value
* of `watchExpression` changes.
* @param {(function()|string)=} listener Callback called whenever the return value of
* the `watchExpression` changes.
*
* - `string`: Evaluated as {@link guide/expression expression}
* - `function(newValue, oldValue, scope)`: called with current and previous values as
* parameters.
*
* - `newVal` contains the current value of the `watchExpression`
* - `oldVal` contains the previous value of the `watchExpression`
* - `scope` refers to the current scope
* @param {boolean=} objectEquality Compare for object equality using {@link angular.equals} instead of
* comparing for reference equality.
* @param {function()=} deregisterNotifier Function to call when the deregistration function
* get called.
* @returns {function()} Returns a deregistration function for this listener.
*/
$watch: function(watchExp, listener, objectEquality, deregisterNotifier) {
var get = compileToFn(watchExp, 'watch');
if (get.$$watchDelegate) {
return get.$$watchDelegate(this, listener, objectEquality, deregisterNotifier, get);
}
$watch: function(watchExp, listener, objectEquality) {
var scope = this,
get = compileToFn(watchExp, 'watch'),
array = scope.$$watchers,
watcher = {
fn: listener,
@@ -344,8 +340,18 @@ function $RootScopeProvider(){
lastDirtyWatch = null;
// in the case user pass string, we need to compile it, do we really need this ?
if (!isFunction(listener)) {
watcher.fn = noop;
var listenFn = compileToFn(listener || noop, 'listener');
watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);};
}
if (typeof watchExp == 'string' && get.constant) {
var originalFn = watcher.fn;
watcher.fn = function(newVal, oldVal, scope) {
originalFn.call(this, newVal, oldVal, scope);
arrayRemove(array, watcher);
};
}
if (!array) {
@@ -358,79 +364,6 @@ function $RootScopeProvider(){
return function deregisterWatch() {
arrayRemove(array, watcher);
lastDirtyWatch = null;
if (isFunction(deregisterNotifier)) {
deregisterNotifier();
}
};
},
/**
* @ngdoc method
* @name $rootScope.Scope#$watchGroup
* @kind function
*
* @description
* A variant of {@link ng.$rootScope.Scope#$watch $watch()} where it watches an array of `watchExpressions`.
* If any one expression in the collection changes the `listener` is executed.
*
* - The items in the `watchExpressions` array are observed via standard $watch operation and are examined on every
* call to $digest() to see if any items changes.
* - The `listener` is called whenever any expression in the `watchExpressions` array changes.
*
* @param {Array.<string|Function(scope)>} watchExpressions Array of expressions that will be individually
* watched using {@link ng.$rootScope.Scope#$watch $watch()}
*
* @param {function(newValues, oldValues, scope)} listener Callback called whenever the return value of any
* expression in `watchExpressions` changes
* The `newValues` array contains the current values of the `watchExpressions`, with the indexes matching
* those of `watchExpression`
* and the `oldValues` array contains the previous values of the `watchExpressions`, with the indexes matching
* those of `watchExpression`
* The `scope` refers to the current scope.
* @returns {function()} Returns a de-registration function for all listeners.
*/
$watchGroup: function(watchExpressions, listener) {
var oldValues = new Array(watchExpressions.length);
var newValues = new Array(watchExpressions.length);
var deregisterFns = [];
var changeCount = 0;
var self = this;
var masterUnwatch;
if (watchExpressions.length === 1) {
// Special case size of one
return this.$watch(watchExpressions[0], function watchGroupAction(value, oldValue, scope) {
newValues[0] = value;
oldValues[0] = oldValue;
listener.call(this, newValues, (value === oldValue) ? newValues : oldValues, scope);
});
}
forEach(watchExpressions, function (expr, i) {
var unwatch = self.$watch(expr, function watchGroupSubAction(value, oldValue) {
newValues[i] = value;
oldValues[i] = oldValue;
changeCount++;
}, false, function watchGroupDeregNotifier() {
arrayRemove(deregisterFns, unwatch);
if (!deregisterFns.length) {
masterUnwatch();
}
});
deregisterFns.push(unwatch);
}, this);
masterUnwatch = self.$watch(function watchGroupChangeWatch() {
return changeCount;
}, function watchGroupChangeAction(value, oldValue) {
listener(newValues, (value === oldValue) ? newValues : oldValues, self);
});
return function deregisterWatchGroup() {
while (deregisterFns.length) {
deregisterFns[0]();
}
};
},
@@ -502,14 +435,14 @@ function $RootScopeProvider(){
// only track veryOldValue if the listener is asking for it
var trackVeryOldValue = (listener.length > 1);
var changeDetected = 0;
var changeDetector = $parse(obj, $watchCollectionInterceptor);
var objGetter = $parse(obj);
var internalArray = [];
var internalObject = {};
var initRun = true;
var oldLength = 0;
function $watchCollectionInterceptor(_value) {
newValue = _value;
function $watchCollectionWatch() {
newValue = objGetter(self);
var newLength, key, bothNaN;
if (!isObject(newValue)) { // if primitive
@@ -610,7 +543,7 @@ function $RootScopeProvider(){
}
}
return this.$watch(changeDetector, $watchCollectionAction);
return this.$watch($watchCollectionWatch, $watchCollectionAction);
},
/**
@@ -630,7 +563,7 @@ function $RootScopeProvider(){
* {@link ng.directive:ngController controllers} or in
* {@link ng.$compileProvider#directive directives}.
* Instead, you should call {@link ng.$rootScope.Scope#$apply $apply()} (typically from within
* a {@link ng.$compileProvider#directive directive}), which will force a `$digest()`.
* a {@link ng.$compileProvider#directive directives}), which will force a `$digest()`.
*
* If you want to be notified whenever `$digest()` is called,
* you can register a `watchExpression` function with
@@ -842,7 +775,7 @@ function $RootScopeProvider(){
// prevent NPEs since these methods have references to properties we nulled out
this.$destroy = this.$digest = this.$apply = noop;
this.$on = this.$watch = this.$watchGroup = function() { return noop; };
this.$on = this.$watch = function() { return noop; };
},
/**
@@ -1000,8 +933,7 @@ function $RootScopeProvider(){
*
* - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or
* `$broadcast`-ed.
* - `currentScope` - `{Scope}`: the scope that is currently handling the event. Once the
* event propagates through the scope hierarchy, this property is set to null.
* - `currentScope` - `{Scope}`: the current scope which is handling the event.
* - `name` - `{string}`: name of the event.
* - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel
* further event propagation (available only for events that were `$emit`-ed).
@@ -1095,16 +1027,11 @@ function $RootScopeProvider(){
}
}
//if any listener on the current scope stops propagation, prevent bubbling
if (stopPropagation) {
event.currentScope = null;
return event;
}
if (stopPropagation) return event;
//traverse upwards
scope = scope.$parent;
} while (scope);
event.currentScope = null;
return event;
},
@@ -1177,7 +1104,6 @@ function $RootScopeProvider(){
}
}
event.currentScope = null;
return event;
}
};
+1 -1
View File
@@ -6,7 +6,7 @@
*/
function $$SanitizeUriProvider() {
var aHrefSanitizationWhitelist = /^\s*(https?|ftp|mailto|tel|file):/,
imgSrcSanitizationWhitelist = /^\s*(https?|ftp|file|blob):|data:image\//;
imgSrcSanitizationWhitelist = /^\s*(https?|ftp|file):|data:image\//;
/**
* @description
+16 -16
View File
@@ -494,7 +494,7 @@ function $SceDelegateProvider() {
* won't work on all browsers. Also, loading templates from `file://` URL does not work on some
* browsers.
*
* ## This feels like too much overhead
* ## This feels like too much overhead for the developer?
*
* It's important to remember that SCE only applies to interpolation expressions.
*
@@ -578,7 +578,7 @@ function $SceDelegateProvider() {
*
* <example module="mySceApp" deps="angular-sanitize.js">
* <file name="index.html">
* <div ng-controller="AppController as myCtrl">
* <div ng-controller="myAppController as myCtrl">
* <i ng-bind-html="myCtrl.explicitlyTrustedHtml" id="explicitlyTrustedHtml"></i><br><br>
* <b>User comments</b><br>
* By default, HTML that isn't explicitly trusted (e.g. Alice's comment) is sanitized when
@@ -595,17 +595,17 @@ function $SceDelegateProvider() {
* </file>
*
* <file name="script.js">
* angular.module('mySceApp', ['ngSanitize'])
* .controller('AppController', ['$http', '$templateCache', '$sce',
* function($http, $templateCache, $sce) {
* var self = this;
* $http.get("test_data.json", {cache: $templateCache}).success(function(userComments) {
* self.userComments = userComments;
* });
* self.explicitlyTrustedHtml = $sce.trustAsHtml(
* '<span onmouseover="this.textContent=&quot;Explicitly trusted HTML bypasses ' +
* 'sanitization.&quot;">Hover over this text.</span>');
* }]);
* var mySceApp = angular.module('mySceApp', ['ngSanitize']);
*
* mySceApp.controller("myAppController", function myAppController($http, $templateCache, $sce) {
* var self = this;
* $http.get("test_data.json", {cache: $templateCache}).success(function(userComments) {
* self.userComments = userComments;
* });
* self.explicitlyTrustedHtml = $sce.trustAsHtml(
* '<span onmouseover="this.textContent=&quot;Explicitly trusted HTML bypasses ' +
* 'sanitization.&quot;">Hover over this text.</span>');
* });
* </file>
*
* <file name="test_data.json">
@@ -787,9 +787,9 @@ function $SceProvider() {
if (parsed.literal && parsed.constant) {
return parsed;
} else {
return $parse(expr, function (value) {
return sce.getTrusted(type, value);
});
return function sceParseAsTrusted(self, locals) {
return sce.getTrusted(type, parsed(self, locals));
};
}
};
+4 -4
View File
@@ -2,8 +2,8 @@
function $TimeoutProvider() {
this.$get = ['$rootScope', '$browser', '$q', '$$q', '$exceptionHandler',
function($rootScope, $browser, $q, $$q, $exceptionHandler) {
this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler',
function($rootScope, $browser, $q, $exceptionHandler) {
var deferreds = {};
@@ -33,9 +33,9 @@ function $TimeoutProvider() {
*
*/
function timeout(fn, delay, invokeApply) {
var skipApply = (isDefined(invokeApply) && !invokeApply),
deferred = (skipApply ? $$q : $q).defer(),
var deferred = $q.defer(),
promise = deferred.promise,
skipApply = (isDefined(invokeApply) && !invokeApply),
timeoutId;
timeoutId = $browser.defer(function() {
+238 -278
View File
@@ -6,8 +6,11 @@
* @name ngAnimate
* @description
*
* # ngAnimate
*
* The `ngAnimate` module provides support for JavaScript, CSS3 transition and CSS3 keyframe animation hooks within existing core and custom directives.
*
*
* <div doc-module-components="ngAnimate"></div>
*
* # Usage
@@ -19,18 +22,17 @@
*
* Below is a more detailed breakdown of the supported animation events provided by pre-existing ng directives:
*
* | Directive | Supported Animations |
* |-----------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------|
* | {@link ng.directive:ngRepeat#usage_animations ngRepeat} | enter, leave and move |
* | {@link ngRoute.directive:ngView#usage_animations ngView} | enter and leave |
* | {@link ng.directive:ngInclude#usage_animations ngInclude} | enter and leave |
* | {@link ng.directive:ngSwitch#usage_animations ngSwitch} | enter and leave |
* | {@link ng.directive:ngIf#usage_animations ngIf} | enter and leave |
* | {@link ng.directive:ngClass#usage_animations ngClass} | add and remove (the CSS class(es) present) |
* | {@link ng.directive:ngShow#usage_animations ngShow} & {@link ng.directive:ngHide#usage_animations ngHide} | add and remove (the ng-hide class value) |
* | {@link ng.directive:form#usage_animations form} & {@link ng.directive:ngModel#usage_animations ngModel} | add and remove (dirty, pristine, valid, invalid & all other validations) |
* | {@link ngMessages.directive:ngMessage#usage_animations ngMessages} | add and remove (ng-active & ng-inactive) |
* | {@link ngMessages.directive:ngMessage#usage_animations ngMessage} | enter and leave |
* | Directive | Supported Animations |
* |---------------------------------------------------------- |----------------------------------------------------|
* | {@link ng.directive:ngRepeat#usage_animations ngRepeat} | enter, leave and move |
* | {@link ngRoute.directive:ngView#usage_animations ngView} | enter and leave |
* | {@link ng.directive:ngInclude#usage_animations ngInclude} | enter and leave |
* | {@link ng.directive:ngSwitch#usage_animations ngSwitch} | enter and leave |
* | {@link ng.directive:ngIf#usage_animations ngIf} | enter and leave |
* | {@link ng.directive:ngClass#usage_animations ngClass} | add and remove |
* | {@link ng.directive:ngShow#usage_animations ngShow & ngHide} | add and remove (the ng-hide class value) |
* | {@link ng.directive:form#usage_animations form} | add and remove (dirty, pristine, valid, invalid & all other validations) |
* | {@link ng.directive:ngModel#usage_animations ngModel} | add and remove (dirty, pristine, valid, invalid & all other validations) |
*
* You can find out more information about animations upon visiting each directive page.
*
@@ -142,74 +144,7 @@
* immediately resulting in a DOM element that is at its final state. This final state is when the DOM element
* has no CSS transition/animation classes applied to it.
*
* ### Structural transition animations
*
* Structural transitions (such as enter, leave and move) will always apply a `0s none` transition
* value to force the browser into rendering the styles defined in the setup (.ng-enter, .ng-leave
* or .ng-move) class. This means that any active transition animations operating on the element
* will be cut off to make way for the enter, leave or move animation.
*
* ### Class-based transition animations
*
* Class-based transitions refer to transition animations that are triggered when a CSS class is
* added to or removed from the element (via `$animate.addClass`, `$animate.removeClass`,
* `$animate.setClass`, or by directives such as `ngClass`, `ngModel` and `form`).
* They are different when compared to structural animations since they **do not cancel existing
* animations** nor do they **block successive transitions** from rendering on the same element.
* This distinction allows for **multiple class-based transitions** to be performed on the same element.
*
* In addition to ngAnimate supporting the default (natural) functionality of class-based transition
* animations, ngAnimate also decorates the element with starting and ending CSS classes to aid the
* developer in further styling the element throughout the transition animation. Earlier versions
* of ngAnimate may have caused natural CSS transitions to break and not render properly due to
* $animate temporarily blocking transitions using `0s none` in order to allow the setup CSS class
* (the `-add` or `-remove` class) to be applied without triggering an animation. However, as of
* **version 1.3**, this workaround has been removed with ngAnimate and all non-ngAnimate CSS
* class transitions are compatible with ngAnimate.
*
* There is, however, one special case when dealing with class-based transitions in ngAnimate.
* When rendering class-based transitions that make use of the setup and active CSS classes
* (e.g. `.fade-add` and `.fade-add-active` for when `.fade` is added) be sure to define
* the transition value **on the active CSS class** and not the setup class.
*
* ```css
* .fade-add {
* /&#42; remember to place a 0s transition here
* to ensure that the styles are applied instantly
* even if the element already has a transition style &#42;/
* transition:0s linear all;
*
* /&#42; starting CSS styles &#42;/
* opacity:1;
* }
* .fade-add.fade-add-active {
* /&#42; this will be the length of the animation &#42;/
* transition:1s linear all;
* opacity:0;
* }
* ```
*
* The setup CSS class (in this case `.fade-add`) also has a transition style property, however, it
* has a duration of zero. This may not be required, however, incase the browser is unable to render
* the styling present in this CSS class instantly then it could be that the browser is attempting
* to perform an unnecessary transition.
*
* This workaround, however, does not apply to standard class-based transitions that are rendered
* when a CSS class containing a transition is applied to an element:
*
* ```css
* .fade {
* /&#42; this works as expected &#42;/
* transition:1s linear all;
* opacity:0;
* }
* ```
*
* Please keep this in mind when coding the CSS markup that will be used within class-based transitions.
* Also, try not to mix the two class-based animation flavors together since the CSS code may become
* overly complex.
*
* ### CSS Staggering Animations
* <h3>CSS Staggering Animations</h3>
* A Staggering animation is a collection of animations that are issued with a slight delay in between each successive operation resulting in a
* curtain-like effect. The ngAnimate module, as of 1.2.0, supports staggering animations and the stagger effect can be
* performed by creating a **ng-EVENT-stagger** CSS class and attaching that class to the base CSS class used for
@@ -425,16 +360,6 @@ angular.module('ngAnimate', ['ng'])
element.data(NG_ANIMATE_STATE, data);
}
function runAnimationPostDigest(fn) {
var cancelFn;
$rootScope.$$postDigest(function() {
cancelFn = fn();
});
return function() {
cancelFn && cancelFn();
};
}
function lookup(name) {
if (name) {
var matches = [],
@@ -638,27 +563,23 @@ angular.module('ngAnimate', ['ng'])
*
* Below is a breakdown of each step that occurs during enter animation:
*
* | Animation Step | What the element class attribute looks like |
* |-------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------|
* | 1. $animate.enter(...) is called | class="my-animation" |
* | 2. element is inserted into the parentElement element or beside the afterElement element | class="my-animation" |
* | 3. $animate waits for the next digest to start the animation | class="my-animation ng-animate" |
* | 4. $animate runs the JavaScript-defined animations detected on the element | class="my-animation ng-animate" |
* | 5. the .ng-enter class is added to the element | class="my-animation ng-animate ng-enter" |
* | 6. $animate scans the element styles to get the CSS transition/animation duration and delay | class="my-animation ng-animate ng-enter" |
* | 7. $animate blocks all CSS transitions on the element to ensure the .ng-enter class styling is applied right away | class="my-animation ng-animate ng-enter" |
* | 8. $animate waits for a single animation frame (this performs a reflow) | class="my-animation ng-animate ng-enter" |
* | 9. $animate removes the CSS transition block placed on the element | class="my-animation ng-animate ng-enter" |
* | 10. the .ng-enter-active class is added (this triggers the CSS transition/animation) | class="my-animation ng-animate ng-enter ng-enter-active" |
* | 11. $animate waits for the animation to complete (via events and timeout) | class="my-animation ng-animate ng-enter ng-enter-active" |
* | 12. The animation ends and all generated CSS classes are removed from the element | class="my-animation" |
* | 13. The doneCallback() callback is fired (if provided) | class="my-animation" |
* | Animation Step | What the element class attribute looks like |
* |----------------------------------------------------------------------------------------------|---------------------------------------------|
* | 1. $animate.enter(...) is called | class="my-animation" |
* | 2. element is inserted into the parentElement element or beside the afterElement element | class="my-animation" |
* | 3. $animate runs any JavaScript-defined animations on the element | class="my-animation ng-animate" |
* | 4. the .ng-enter class is added to the element | class="my-animation ng-animate ng-enter" |
* | 5. $animate scans the element styles to get the CSS transition/animation duration and delay | class="my-animation ng-animate ng-enter" |
* | 6. $animate waits for 10ms (this performs a reflow) | class="my-animation ng-animate ng-enter" |
* | 7. the .ng-enter-active and .ng-animate-active classes are added (this triggers the CSS transition/animation) | class="my-animation ng-animate ng-animate-active ng-enter ng-enter-active" |
* | 8. $animate waits for X milliseconds for the animation to complete | class="my-animation ng-animate ng-animate-active ng-enter ng-enter-active" |
* | 9. The animation ends and all generated CSS classes are removed from the element | class="my-animation" |
* | 10. The doneCallback() callback is fired (if provided) | class="my-animation" |
*
* @param {DOMElement} element the element that will be the focus of the enter animation
* @param {DOMElement} parentElement the parent element of the element that will be the focus of the enter animation
* @param {DOMElement} afterElement the sibling element (which is the previous element) of the element that will be the focus of the enter animation
* @param {function()=} doneCallback the callback function that will be called once the animation is complete
* @return {function} the animation cancellation function
*/
enter : function(element, parentElement, afterElement, doneCallback) {
element = angular.element(element);
@@ -667,8 +588,9 @@ angular.module('ngAnimate', ['ng'])
blockElementAnimations(element);
$delegate.enter(element, parentElement, afterElement);
return runAnimationPostDigest(function() {
return performAnimation('enter', 'ng-enter', stripCommentsFromElement(element), parentElement, afterElement, noop, doneCallback);
$rootScope.$$postDigest(function() {
element = stripCommentsFromElement(element);
performAnimation('enter', 'ng-enter', element, parentElement, afterElement, noop, doneCallback);
});
},
@@ -683,34 +605,28 @@ angular.module('ngAnimate', ['ng'])
*
* Below is a breakdown of each step that occurs during leave animation:
*
* | Animation Step | What the element class attribute looks like |
* |-------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------|
* | 1. $animate.leave(...) is called | class="my-animation" |
* | 2. $animate runs the JavaScript-defined animations detected on the element | class="my-animation ng-animate" |
* | 3. $animate waits for the next digest to start the animation | class="my-animation ng-animate" |
* | 4. the .ng-leave class is added to the element | class="my-animation ng-animate ng-leave" |
* | 5. $animate scans the element styles to get the CSS transition/animation duration and delay | class="my-animation ng-animate ng-leave" |
* | 6. $animate blocks all CSS transitions on the element to ensure the .ng-leave class styling is applied right away | class="my-animation ng-animate ng-leave” |
* | 7. $animate waits for a single animation frame (this performs a reflow) | class="my-animation ng-animate ng-leave" |
* | 8. $animate removes the CSS transition block placed on the element | class="my-animation ng-animate ng-leave” |
* | 9. the .ng-leave-active class is added (this triggers the CSS transition/animation) | class="my-animation ng-animate ng-leave ng-leave-active" |
* | 10. $animate waits for the animation to complete (via events and timeout) | class="my-animation ng-animate ng-leave ng-leave-active" |
* | 11. The animation ends and all generated CSS classes are removed from the element | class="my-animation" |
* | 12. The element is removed from the DOM | ... |
* | 13. The doneCallback() callback is fired (if provided) | ... |
* | Animation Step | What the element class attribute looks like |
* |----------------------------------------------------------------------------------------------|---------------------------------------------|
* | 1. $animate.leave(...) is called | class="my-animation" |
* | 2. $animate runs any JavaScript-defined animations on the element | class="my-animation ng-animate" |
* | 3. the .ng-leave class is added to the element | class="my-animation ng-animate ng-leave" |
* | 4. $animate scans the element styles to get the CSS transition/animation duration and delay | class="my-animation ng-animate ng-leave" |
* | 5. $animate waits for 10ms (this performs a reflow) | class="my-animation ng-animate ng-leave" |
* | 6. the .ng-leave-active and .ng-animate-active classes is added (this triggers the CSS transition/animation) | class="my-animation ng-animate ng-animate-active ng-leave ng-leave-active" |
* | 7. $animate waits for X milliseconds for the animation to complete | class="my-animation ng-animate ng-animate-active ng-leave ng-leave-active" |
* | 8. The animation ends and all generated CSS classes are removed from the element | class="my-animation" |
* | 9. The element is removed from the DOM | ... |
* | 10. The doneCallback() callback is fired (if provided) | ... |
*
* @param {DOMElement} element the element that will be the focus of the leave animation
* @param {function()=} doneCallback the callback function that will be called once the animation is complete
* @return {function} the animation cancellation function
*/
leave : function(element, doneCallback) {
element = angular.element(element);
cancelChildAnimations(element);
blockElementAnimations(element);
this.enabled(false, element);
return runAnimationPostDigest(function() {
return performAnimation('leave', 'ng-leave', stripCommentsFromElement(element), null, null, function() {
$rootScope.$$postDigest(function() {
performAnimation('leave', 'ng-leave', stripCommentsFromElement(element), null, null, function() {
$delegate.leave(element);
}, doneCallback);
});
@@ -728,27 +644,23 @@ angular.module('ngAnimate', ['ng'])
*
* Below is a breakdown of each step that occurs during move animation:
*
* | Animation Step | What the element class attribute looks like |
* |------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------|
* | 1. $animate.move(...) is called | class="my-animation" |
* | 2. element is moved into the parentElement element or beside the afterElement element | class="my-animation" |
* | 3. $animate waits for the next digest to start the animation | class="my-animation ng-animate" |
* | 4. $animate runs the JavaScript-defined animations detected on the element | class="my-animation ng-animate" |
* | 5. the .ng-move class is added to the element | class="my-animation ng-animate ng-move" |
* | 6. $animate scans the element styles to get the CSS transition/animation duration and delay | class="my-animation ng-animate ng-move" |
* | 7. $animate blocks all CSS transitions on the element to ensure the .ng-move class styling is applied right away | class="my-animation ng-animate ng-move” |
* | 8. $animate waits for a single animation frame (this performs a reflow) | class="my-animation ng-animate ng-move" |
* | 9. $animate removes the CSS transition block placed on the element | class="my-animation ng-animate ng-move” |
* | 10. the .ng-move-active class is added (this triggers the CSS transition/animation) | class="my-animation ng-animate ng-move ng-move-active" |
* | 11. $animate waits for the animation to complete (via events and timeout) | class="my-animation ng-animate ng-move ng-move-active" |
* | 12. The animation ends and all generated CSS classes are removed from the element | class="my-animation" |
* | 13. The doneCallback() callback is fired (if provided) | class="my-animation" |
* | Animation Step | What the element class attribute looks like |
* |----------------------------------------------------------------------------------------------|---------------------------------------------|
* | 1. $animate.move(...) is called | class="my-animation" |
* | 2. element is moved into the parentElement element or beside the afterElement element | class="my-animation" |
* | 3. $animate runs any JavaScript-defined animations on the element | class="my-animation ng-animate" |
* | 4. the .ng-move class is added to the element | class="my-animation ng-animate ng-move" |
* | 5. $animate scans the element styles to get the CSS transition/animation duration and delay | class="my-animation ng-animate ng-move" |
* | 6. $animate waits for 10ms (this performs a reflow) | class="my-animation ng-animate ng-move" |
* | 7. the .ng-move-active and .ng-animate-active classes is added (this triggers the CSS transition/animation) | class="my-animation ng-animate ng-animate-active ng-move ng-move-active" |
* | 8. $animate waits for X milliseconds for the animation to complete | class="my-animation ng-animate ng-animate-active ng-move ng-move-active" |
* | 9. The animation ends and all generated CSS classes are removed from the element | class="my-animation" |
* | 10. The doneCallback() callback is fired (if provided) | class="my-animation" |
*
* @param {DOMElement} element the element that will be the focus of the move animation
* @param {DOMElement} parentElement the parentElement element of the element that will be the focus of the move animation
* @param {DOMElement} afterElement the sibling element (which is the previous element) of the element that will be the focus of the move animation
* @param {function()=} doneCallback the callback function that will be called once the animation is complete
* @return {function} the animation cancellation function
*/
move : function(element, parentElement, afterElement, doneCallback) {
element = angular.element(element);
@@ -758,8 +670,9 @@ angular.module('ngAnimate', ['ng'])
cancelChildAnimations(element);
blockElementAnimations(element);
$delegate.move(element, parentElement, afterElement);
return runAnimationPostDigest(function() {
return performAnimation('move', 'ng-move', stripCommentsFromElement(element), parentElement, afterElement, noop, doneCallback);
$rootScope.$$postDigest(function() {
element = stripCommentsFromElement(element);
performAnimation('move', 'ng-move', element, parentElement, afterElement, noop, doneCallback);
});
},
@@ -771,32 +684,31 @@ angular.module('ngAnimate', ['ng'])
* Triggers a custom animation event based off the className variable and then attaches the className value to the element as a CSS class.
* Unlike the other animation methods, the animate service will suffix the className value with {@type -add} in order to provide
* the animate service the setup and active CSS classes in order to trigger the animation (this will be skipped if no CSS transitions
* or keyframes are defined on the -add-active or base CSS class).
* or keyframes are defined on the -add or base CSS class).
*
* Below is a breakdown of each step that occurs during addClass animation:
*
* | Animation Step | What the element class attribute looks like |
* |----------------------------------------------------------------------------------------------------|------------------------------------------------------------------|
* | 1. $animate.addClass(element, 'super') is called | class="my-animation" |
* | 2. $animate runs the JavaScript-defined animations detected on the element | class="my-animation ng-animate" |
* | 3. the .super-add class is added to the element | class="my-animation ng-animate super-add" |
* | 4. $animate waits for a single animation frame (this performs a reflow) | class="my-animation ng-animate super-add" |
* | 5. the .super and .super-add-active classes are added (this triggers the CSS transition/animation) | class="my-animation ng-animate super super-add super-add-active" |
* | 6. $animate scans the element styles to get the CSS transition/animation duration and delay | class="my-animation ng-animate super-add" |
* | 7. $animate waits for the animation to complete (via events and timeout) | class="my-animation super super-add super-add-active" |
* | 8. The animation ends and all generated CSS classes are removed from the element | class="my-animation super" |
* | 9. The super class is kept on the element | class="my-animation super" |
* | 10. The doneCallback() callback is fired (if provided) | class="my-animation super" |
* | Animation Step | What the element class attribute looks like |
* |------------------------------------------------------------------------------------------------|---------------------------------------------|
* | 1. $animate.addClass(element, 'super') is called | class="my-animation" |
* | 2. $animate runs any JavaScript-defined animations on the element | class="my-animation ng-animate" |
* | 3. the .super-add class are added to the element | class="my-animation ng-animate super-add" |
* | 4. $animate scans the element styles to get the CSS transition/animation duration and delay | class="my-animation ng-animate super-add" |
* | 5. $animate waits for 10ms (this performs a reflow) | class="my-animation ng-animate super-add" |
* | 6. the .super, .super-add-active and .ng-animate-active classes are added (this triggers the CSS transition/animation) | class="my-animation ng-animate ng-animate-active super super-add super-add-active" |
* | 7. $animate waits for X milliseconds for the animation to complete | class="my-animation super super-add super-add-active" |
* | 8. The animation ends and all generated CSS classes are removed from the element | class="my-animation super" |
* | 9. The super class is kept on the element | class="my-animation super" |
* | 10. The doneCallback() callback is fired (if provided) | class="my-animation super" |
*
* @param {DOMElement} element the element that will be animated
* @param {string} className the CSS class that will be added to the element and then animated
* @param {function()=} doneCallback the callback function that will be called once the animation is complete
* @return {function} the animation cancellation function
*/
addClass : function(element, className, doneCallback) {
element = angular.element(element);
element = stripCommentsFromElement(element);
return performAnimation('addClass', className, element, null, null, function() {
performAnimation('addClass', className, element, null, null, function() {
$delegate.addClass(element, className);
}, doneCallback);
},
@@ -813,64 +725,49 @@ angular.module('ngAnimate', ['ng'])
*
* Below is a breakdown of each step that occurs during removeClass animation:
*
* | Animation Step | What the element class attribute looks like |
* |------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------|
* | 1. $animate.removeClass(element, 'super') is called | class="my-animation super" |
* | 2. $animate runs the JavaScript-defined animations detected on the element | class="my-animation super ng-animate" |
* | 3. the .super-remove class is added to the element | class="my-animation super ng-animate super-remove" |
* | 4. $animate waits for a single animation frame (this performs a reflow) | class="my-animation super ng-animate super-remove" |
* | 5. the .super-remove-active classes are added and .super is removed (this triggers the CSS transition/animation) | class="my-animation ng-animate super-remove super-remove-active" |
* | 6. $animate scans the element styles to get the CSS transition/animation duration and delay | class="my-animation super ng-animate super-remove" |
* | 7. $animate waits for the animation to complete (via events and timeout) | class="my-animation ng-animate super-remove super-remove-active" |
* | 8. The animation ends and all generated CSS classes are removed from the element | class="my-animation" |
* | 9. The doneCallback() callback is fired (if provided) | class="my-animation" |
* | Animation Step | What the element class attribute looks like |
* |-----------------------------------------------------------------------------------------------|---------------------------------------------|
* | 1. $animate.removeClass(element, 'super') is called | class="my-animation super" |
* | 2. $animate runs any JavaScript-defined animations on the element | class="my-animation super ng-animate" |
* | 3. the .super-remove class are added to the element | class="my-animation super ng-animate super-remove"|
* | 4. $animate scans the element styles to get the CSS transition/animation duration and delay | class="my-animation super ng-animate super-remove" |
* | 5. $animate waits for 10ms (this performs a reflow) | class="my-animation super ng-animate super-remove" |
* | 6. the .super-remove-active and .ng-animate-active classes are added and .super is removed (this triggers the CSS transition/animation) | class="my-animation ng-animate ng-animate-active super-remove super-remove-active" |
* | 7. $animate waits for X milliseconds for the animation to complete | class="my-animation ng-animate ng-animate-active super-remove super-remove-active" |
* | 8. The animation ends and all generated CSS classes are removed from the element | class="my-animation" |
* | 9. The doneCallback() callback is fired (if provided) | class="my-animation" |
*
*
* @param {DOMElement} element the element that will be animated
* @param {string} className the CSS class that will be animated and then removed from the element
* @param {function()=} doneCallback the callback function that will be called once the animation is complete
* @return {function} the animation cancellation function
*/
removeClass : function(element, className, doneCallback) {
element = angular.element(element);
element = stripCommentsFromElement(element);
return performAnimation('removeClass', className, element, null, null, function() {
performAnimation('removeClass', className, element, null, null, function() {
$delegate.removeClass(element, className);
}, doneCallback);
},
/**
*
* @ngdoc method
* @name $animate#setClass
*
* @description Adds and/or removes the given CSS classes to and from the element.
* Once complete, the done() callback will be fired (if provided).
*
* | Animation Step | What the element class attribute looks like |
* |--------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------|
* | 1. $animate.removeClass(element, on, off) is called | class="my-animation super off” |
* | 2. $animate runs the JavaScript-defined animations detected on the element | class="my-animation super ng-animate off” |
* | 3. the .on-add and .off-remove classes are added to the element | class="my-animation ng-animate on-add off-remove off” |
* | 4. $animate waits for a single animation frame (this performs a reflow) | class="my-animation ng-animate on-add off-remove off” |
* | 5. the .on, .on-add-active and .off-remove-active classes are added and .off is removed (this triggers the CSS transition/animation) | class="my-animation ng-animate on on-add on-add-active off-remove off-remove-active” |
* | 6. $animate scans the element styles to get the CSS transition/animation duration and delay | class="my-animation ng-animate on on-add on-add-active off-remove off-remove-active" |
* | 7. $animate waits for the animation to complete (via events and timeout) | class="my-animation ng-animate on on-add on-add-active off-remove off-remove-active" |
* | 8. The animation ends and all generated CSS classes are removed from the element | class="my-animation" |
* | 9. The doneCallback() callback is fired (if provided) | class="my-animation" |
*
* @param {DOMElement} element the element which will have its CSS classes changed
* removed from it
* @param {string} add the CSS classes which will be added to the element
* @param {string} remove the CSS class which will be removed from the element
* @param {function=} done the callback function (if provided) that will be fired after the
* CSS classes have been set on the element
* @return {function} the animation cancellation function
*/
/**
*
* @ngdoc function
* @name $animate#setClass
* @function
* @description Adds and/or removes the given CSS classes to and from the element.
* Once complete, the done() callback will be fired (if provided).
* @param {DOMElement} element the element which will its CSS classes changed
* removed from it
* @param {string} add the CSS classes which will be added to the element
* @param {string} remove the CSS class which will be removed from the element
* @param {Function=} done the callback function (if provided) that will be fired after the
* CSS classes have been set on the element
*/
setClass : function(element, add, remove, doneCallback) {
element = angular.element(element);
element = stripCommentsFromElement(element);
return performAnimation('setClass', [add, remove], element, null, null, function() {
performAnimation('setClass', [add, remove], element, null, null, function() {
$delegate.setClass(element, add, remove);
}, doneCallback);
},
@@ -921,14 +818,13 @@ angular.module('ngAnimate', ['ng'])
*/
function performAnimation(animationEvent, className, element, parentElement, afterElement, domOperation, doneCallback) {
var noopCancel = noop;
var runner = animationRunner(element, animationEvent, className);
if(!runner) {
fireDOMOperation();
fireBeforeCallbackAsync();
fireAfterCallbackAsync();
closeAnimation();
return noopCancel;
return;
}
className = runner.className;
@@ -962,7 +858,7 @@ angular.module('ngAnimate', ['ng'])
fireBeforeCallbackAsync();
fireAfterCallbackAsync();
closeAnimation();
return noopCancel;
return;
}
var skipAnimation = false;
@@ -975,9 +871,10 @@ angular.module('ngAnimate', ['ng'])
//cancel all animations when a structural animation takes place
for(var klass in runningAnimations) {
animationsToCancel.push(runningAnimations[klass]);
cleanup(element, klass);
}
ngAnimateState = {};
cleanup(element, true);
runningAnimations = {};
totalActiveAnimations = 0;
}
} else if(lastAnimation.event == 'setClass') {
animationsToCancel.push(lastAnimation);
@@ -1000,9 +897,6 @@ angular.module('ngAnimate', ['ng'])
}
}
runningAnimations = ngAnimateState.active || {};
totalActiveAnimations = ngAnimateState.totalActive || 0;
if(runner.isClassBased && !runner.isSetClassOperation && !skipAnimation) {
skipAnimation = (animationEvent == 'addClass') == element.hasClass(className); //opposite of XOR
}
@@ -1012,7 +906,7 @@ angular.module('ngAnimate', ['ng'])
fireBeforeCallbackAsync();
fireAfterCallbackAsync();
fireDoneCallbackAsync();
return noopCancel;
return;
}
if(animationEvent == 'leave') {
@@ -1065,8 +959,6 @@ angular.module('ngAnimate', ['ng'])
}
});
return runner.cancel;
function fireDOMCallback(animationPhase) {
var eventName = '$animate:' + animationPhase;
if(elementEvents && elementEvents[eventName] && elementEvents[eventName].length > 0) {
@@ -1255,6 +1147,7 @@ angular.module('ngAnimate', ['ng'])
var ANIMATION_ITERATION_COUNT_KEY = 'IterationCount';
var NG_ANIMATE_PARENT_KEY = '$$ngAnimateKey';
var NG_ANIMATE_CSS_DATA_KEY = '$$ngAnimateCSS3Data';
var NG_ANIMATE_BLOCK_CLASS_NAME = 'ng-animate-block-transitions';
var ELAPSED_TIME_MAX_DECIMAL_PLACES = 3;
var CLOSING_TIME_BUFFER = 1.5;
var ONE_SECOND = 1000;
@@ -1310,9 +1203,7 @@ angular.module('ngAnimate', ['ng'])
forEach(elements, function(element) {
var elementData = element.data(NG_ANIMATE_CSS_DATA_KEY);
if(elementData) {
forEach(elementData.closeAnimationFns, function(fn) {
fn();
});
(elementData.closeAnimationFn || noop)();
}
});
}
@@ -1396,9 +1287,7 @@ angular.module('ngAnimate', ['ng'])
return parentID + '-' + extractElementNode(element).getAttribute('class');
}
function animateSetup(animationEvent, element, className) {
var structural = ['ng-enter','ng-leave','ng-move'].indexOf(className) >= 0;
function animateSetup(animationEvent, element, className, calculationDecorator) {
var cacheKey = getCacheKey(element);
var eventCacheKey = cacheKey + ' ' + className;
var itemIndex = lookupCache[eventCacheKey] ? ++lookupCache[eventCacheKey].total : 0;
@@ -1416,47 +1305,87 @@ angular.module('ngAnimate', ['ng'])
applyClasses && element.removeClass(staggerClassName);
}
/* the animation itself may need to add/remove special CSS classes
* before calculating the anmation styles */
calculationDecorator = calculationDecorator ||
function(fn) { return fn(); };
element.addClass(className);
var formerData = element.data(NG_ANIMATE_CSS_DATA_KEY) || {};
var timings = getElementAnimationDetails(element, eventCacheKey);
var timings = calculationDecorator(function() {
return getElementAnimationDetails(element, eventCacheKey);
});
var transitionDuration = timings.transitionDuration;
var animationDuration = timings.animationDuration;
if(structural && transitionDuration === 0 && animationDuration === 0) {
if(transitionDuration === 0 && animationDuration === 0) {
element.removeClass(className);
return false;
}
var blockTransition = structural && transitionDuration > 0;
var blockAnimation = animationDuration > 0 &&
stagger.animationDelay > 0 &&
stagger.animationDuration === 0;
var closeAnimationFns = formerData.closeAnimationFns || [];
element.data(NG_ANIMATE_CSS_DATA_KEY, {
stagger : stagger,
cacheKey : eventCacheKey,
running : formerData.running || 0,
itemIndex : itemIndex,
blockTransition : blockTransition,
blockAnimation : blockAnimation,
closeAnimationFns : closeAnimationFns
stagger : stagger,
timings : timings,
closeAnimationFn : noop
});
var node = extractElementNode(element);
if(blockTransition) {
node.style[TRANSITION_PROP + PROPERTY_KEY] = 'none';
//temporarily disable the transition so that the enter styles
//don't animate twice (this is here to avoid a bug in Chrome/FF).
var isCurrentlyAnimating = formerData.running > 0 || animationEvent == 'setClass';
if(transitionDuration > 0) {
blockTransitions(element, className, isCurrentlyAnimating);
}
if(blockAnimation) {
node.style[ANIMATION_PROP] = 'none 0s';
//staggering keyframe animations work by adjusting the `animation-delay` CSS property
//on the given element, however, the delay value can only calculated after the reflow
//since by that time $animate knows how many elements are being animated. Therefore,
//until the reflow occurs the element needs to be blocked (where the keyframe animation
//is set to `none 0s`). This blocking mechanism should only be set for when a stagger
//animation is detected and when the element item index is greater than 0.
if(animationDuration > 0 && stagger.animationDelay > 0 && stagger.animationDuration === 0) {
blockKeyframeAnimations(element);
}
return true;
}
function isStructuralAnimation(className) {
return className == 'ng-enter' || className == 'ng-move' || className == 'ng-leave';
}
function blockTransitions(element, className, isAnimating) {
if(isStructuralAnimation(className) || !isAnimating) {
extractElementNode(element).style[TRANSITION_PROP + PROPERTY_KEY] = 'none';
} else {
element.addClass(NG_ANIMATE_BLOCK_CLASS_NAME);
}
}
function blockKeyframeAnimations(element) {
extractElementNode(element).style[ANIMATION_PROP] = 'none 0s';
}
function unblockTransitions(element, className) {
var prop = TRANSITION_PROP + PROPERTY_KEY;
var node = extractElementNode(element);
if(node.style[prop] && node.style[prop].length > 0) {
node.style[prop] = '';
}
element.removeClass(NG_ANIMATE_BLOCK_CLASS_NAME);
}
function unblockKeyframeAnimations(element) {
var prop = ANIMATION_PROP;
var node = extractElementNode(element);
if(node.style[prop] && node.style[prop].length > 0) {
node.style[prop] = '';
}
}
function animateRun(animationEvent, element, className, activeAnimationComplete) {
var node = extractElementNode(element);
var elementData = element.data(NG_ANIMATE_CSS_DATA_KEY);
@@ -1465,36 +1394,21 @@ angular.module('ngAnimate', ['ng'])
return;
}
if(elementData.blockTransition) {
node.style[TRANSITION_PROP + PROPERTY_KEY] = '';
}
if(elementData.blockAnimation) {
node.style[ANIMATION_PROP] = '';
}
var activeClassName = '';
forEach(className.split(' '), function(klass, i) {
activeClassName += (i > 0 ? ' ' : '') + klass + '-active';
});
element.addClass(activeClassName);
var eventCacheKey = elementData.cacheKey + ' ' + activeClassName;
var timings = getElementAnimationDetails(element, eventCacheKey);
var maxDuration = Math.max(timings.transitionDuration, timings.animationDuration);
if(maxDuration === 0) {
element.removeClass(activeClassName);
animateClose(element, className);
activeAnimationComplete();
return;
}
var maxDelay = Math.max(timings.transitionDelay, timings.animationDelay);
var stagger = elementData.stagger;
var timings = elementData.timings;
var itemIndex = elementData.itemIndex;
var maxDuration = Math.max(timings.transitionDuration, timings.animationDuration);
var maxDelay = Math.max(timings.transitionDelay, timings.animationDelay);
var maxDelayTime = maxDelay * ONE_SECOND;
var startTime = Date.now();
var css3AnimationEvents = ANIMATIONEND_EVENT + ' ' + TRANSITIONEND_EVENT;
var style = '', appliedStyles = [];
if(timings.transitionDuration > 0) {
var propertyStyle = timings.transitionPropertyStyle;
@@ -1529,14 +1443,12 @@ angular.module('ngAnimate', ['ng'])
node.setAttribute('style', oldStyle + '; ' + style);
}
var startTime = Date.now();
var css3AnimationEvents = ANIMATIONEND_EVENT + ' ' + TRANSITIONEND_EVENT;
element.on(css3AnimationEvents, onAnimationProgress);
elementData.closeAnimationFns.push(function() {
element.addClass(activeClassName);
elementData.closeAnimationFn = function() {
onEnd();
activeAnimationComplete();
});
};
var staggerTime = itemIndex * (Math.max(stagger.animationDelay, stagger.transitionDelay) || 0);
var animationTime = (maxDelay + maxDuration) * CLOSING_TIME_BUFFER;
@@ -1624,6 +1536,8 @@ angular.module('ngAnimate', ['ng'])
//happen in the first place
var cancel = preReflowCancellation;
afterReflow(element, function() {
unblockTransitions(element, className);
unblockKeyframeAnimations(element);
//once the reflow is complete then we point cancel to
//the new cancellation function which will remove all of the
//animation properties from the active animation
@@ -1664,27 +1578,49 @@ angular.module('ngAnimate', ['ng'])
beforeSetClass : function(element, add, remove, animationCompleted) {
var className = suffixClasses(remove, '-remove') + ' ' +
suffixClasses(add, '-add');
var cancellationMethod = animateBefore('setClass', element, className);
var cancellationMethod = animateBefore('setClass', element, className, function(fn) {
/* when classes are removed from an element then the transition style
* that is applied is the transition defined on the element without the
* CSS class being there. This is how CSS3 functions outside of ngAnimate.
* http://plnkr.co/edit/j8OzgTNxHTb4n3zLyjGW?p=preview */
var klass = element.attr('class');
element.removeClass(remove);
element.addClass(add);
var timings = fn();
element.attr('class', klass);
return timings;
});
if(cancellationMethod) {
afterReflow(element, animationCompleted);
afterReflow(element, function() {
unblockTransitions(element, className);
unblockKeyframeAnimations(element);
animationCompleted();
});
return cancellationMethod;
}
animationCompleted();
},
beforeAddClass : function(element, className, animationCompleted) {
var cancellationMethod = animateBefore('addClass', element, suffixClasses(className, '-add'));
if(cancellationMethod) {
afterReflow(element, animationCompleted);
return cancellationMethod;
}
animationCompleted();
},
var cancellationMethod = animateBefore('addClass', element, suffixClasses(className, '-add'), function(fn) {
/* when a CSS class is added to an element then the transition style that
* is applied is the transition defined on the element when the CSS class
* is added at the time of the animation. This is how CSS3 functions
* outside of ngAnimate. */
element.addClass(className);
var timings = fn();
element.removeClass(className);
return timings;
});
beforeRemoveClass : function(element, className, animationCompleted) {
var cancellationMethod = animateBefore('removeClass', element, suffixClasses(className, '-remove'));
if(cancellationMethod) {
afterReflow(element, animationCompleted);
afterReflow(element, function() {
unblockTransitions(element, className);
unblockKeyframeAnimations(element);
animationCompleted();
});
return cancellationMethod;
}
animationCompleted();
@@ -1701,6 +1637,30 @@ angular.module('ngAnimate', ['ng'])
return animateAfter('addClass', element, suffixClasses(className, '-add'), animationCompleted);
},
beforeRemoveClass : function(element, className, animationCompleted) {
var cancellationMethod = animateBefore('removeClass', element, suffixClasses(className, '-remove'), function(fn) {
/* when classes are removed from an element then the transition style
* that is applied is the transition defined on the element without the
* CSS class being there. This is how CSS3 functions outside of ngAnimate.
* http://plnkr.co/edit/j8OzgTNxHTb4n3zLyjGW?p=preview */
var klass = element.attr('class');
element.removeClass(className);
var timings = fn();
element.attr('class', klass);
return timings;
});
if(cancellationMethod) {
afterReflow(element, function() {
unblockTransitions(element, className);
unblockKeyframeAnimations(element);
animationCompleted();
});
return cancellationMethod;
}
animationCompleted();
},
removeClass : function(element, className, animationCompleted) {
return animateAfter('removeClass', element, suffixClasses(className, '-remove'), animationCompleted);
}
+5 -5
View File
@@ -58,8 +58,8 @@ $provide.value("$locale", {
"medium": "d MMM y HH:mm:ss",
"mediumDate": "d MMM y",
"mediumTime": "HH:mm:ss",
"short": "y-MM-dd HH:mm",
"shortDate": "y-MM-dd",
"short": "yyyy-MM-dd HH:mm",
"shortDate": "yyyy-MM-dd",
"shortTime": "HH:mm"
},
"NUMBER_FORMATS": {
@@ -86,14 +86,14 @@ $provide.value("$locale", {
"maxFrac": 2,
"minFrac": 2,
"minInt": 1,
"negPre": "\u00a4-",
"negSuf": "",
"negPre": "(\u00a4",
"negSuf": ")",
"posPre": "\u00a4",
"posSuf": ""
}
]
},
"id": "af-na",
"pluralCat": function (n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
"pluralCat": function (n) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
});
}]);
+5 -5
View File
@@ -58,8 +58,8 @@ $provide.value("$locale", {
"medium": "dd MMM y h:mm:ss a",
"mediumDate": "dd MMM y",
"mediumTime": "h:mm:ss a",
"short": "y-MM-dd h:mm a",
"shortDate": "y-MM-dd",
"short": "yyyy-MM-dd h:mm a",
"shortDate": "yyyy-MM-dd",
"shortTime": "h:mm a"
},
"NUMBER_FORMATS": {
@@ -86,14 +86,14 @@ $provide.value("$locale", {
"maxFrac": 2,
"minFrac": 2,
"minInt": 1,
"negPre": "\u00a4-",
"negSuf": "",
"negPre": "(\u00a4",
"negSuf": ")",
"posPre": "\u00a4",
"posSuf": ""
}
]
},
"id": "af-za",
"pluralCat": function (n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
"pluralCat": function (n) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
});
}]);
+5 -5
View File
@@ -58,8 +58,8 @@ $provide.value("$locale", {
"medium": "dd MMM y h:mm:ss a",
"mediumDate": "dd MMM y",
"mediumTime": "h:mm:ss a",
"short": "y-MM-dd h:mm a",
"shortDate": "y-MM-dd",
"short": "yyyy-MM-dd h:mm a",
"shortDate": "yyyy-MM-dd",
"shortTime": "h:mm a"
},
"NUMBER_FORMATS": {
@@ -86,14 +86,14 @@ $provide.value("$locale", {
"maxFrac": 2,
"minFrac": 2,
"minInt": 1,
"negPre": "\u00a4-",
"negSuf": "",
"negPre": "(\u00a4",
"negSuf": ")",
"posPre": "\u00a4",
"posSuf": ""
}
]
},
"id": "af",
"pluralCat": function (n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
"pluralCat": function (n) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
});
}]);
+9 -9
View File
@@ -4,8 +4,8 @@ var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "
$provide.value("$locale", {
"DATETIME_FORMATS": {
"AMPMS": [
"\u1325\u12cb\u1275",
"\u12a8\u1230\u12d3\u1275"
"\u1321\u12cb\u1275",
"\u12a8\u1233\u12d3\u1275"
],
"DAY": [
"\u12a5\u1211\u12f5",
@@ -20,7 +20,7 @@ $provide.value("$locale", {
"\u1303\u1295\u12e9\u12c8\u122a",
"\u134c\u1265\u1229\u12c8\u122a",
"\u121b\u122d\u127d",
"\u12a4\u1355\u122a\u120d",
"\u12a4\u1355\u1228\u120d",
"\u121c\u12ed",
"\u1301\u1295",
"\u1301\u120b\u12ed",
@@ -43,7 +43,7 @@ $provide.value("$locale", {
"\u1303\u1295\u12e9",
"\u134c\u1265\u1229",
"\u121b\u122d\u127d",
"\u12a4\u1355\u122a",
"\u12a4\u1355\u1228",
"\u121c\u12ed",
"\u1301\u1295",
"\u1301\u120b\u12ed",
@@ -58,8 +58,8 @@ $provide.value("$locale", {
"medium": "d MMM y h:mm:ss a",
"mediumDate": "d MMM y",
"mediumTime": "h:mm:ss a",
"short": "dd/MM/y h:mm a",
"shortDate": "dd/MM/y",
"short": "dd/MM/yyyy h:mm a",
"shortDate": "dd/MM/yyyy",
"shortTime": "h:mm a"
},
"NUMBER_FORMATS": {
@@ -86,14 +86,14 @@ $provide.value("$locale", {
"maxFrac": 2,
"minFrac": 2,
"minInt": 1,
"negPre": "\u00a4-",
"negSuf": "",
"negPre": "(\u00a4",
"negSuf": ")",
"posPre": "\u00a4",
"posSuf": ""
}
]
},
"id": "am-et",
"pluralCat": function (n, opt_precision) { var i = n | 0; if (i == 0 || n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
"pluralCat": function (n) { if (n == 0 || n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
});
}]);
+9 -9
View File
@@ -4,8 +4,8 @@ var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "
$provide.value("$locale", {
"DATETIME_FORMATS": {
"AMPMS": [
"\u1325\u12cb\u1275",
"\u12a8\u1230\u12d3\u1275"
"\u1321\u12cb\u1275",
"\u12a8\u1233\u12d3\u1275"
],
"DAY": [
"\u12a5\u1211\u12f5",
@@ -20,7 +20,7 @@ $provide.value("$locale", {
"\u1303\u1295\u12e9\u12c8\u122a",
"\u134c\u1265\u1229\u12c8\u122a",
"\u121b\u122d\u127d",
"\u12a4\u1355\u122a\u120d",
"\u12a4\u1355\u1228\u120d",
"\u121c\u12ed",
"\u1301\u1295",
"\u1301\u120b\u12ed",
@@ -43,7 +43,7 @@ $provide.value("$locale", {
"\u1303\u1295\u12e9",
"\u134c\u1265\u1229",
"\u121b\u122d\u127d",
"\u12a4\u1355\u122a",
"\u12a4\u1355\u1228",
"\u121c\u12ed",
"\u1301\u1295",
"\u1301\u120b\u12ed",
@@ -58,8 +58,8 @@ $provide.value("$locale", {
"medium": "d MMM y h:mm:ss a",
"mediumDate": "d MMM y",
"mediumTime": "h:mm:ss a",
"short": "dd/MM/y h:mm a",
"shortDate": "dd/MM/y",
"short": "dd/MM/yyyy h:mm a",
"shortDate": "dd/MM/yyyy",
"shortTime": "h:mm a"
},
"NUMBER_FORMATS": {
@@ -86,14 +86,14 @@ $provide.value("$locale", {
"maxFrac": 2,
"minFrac": 2,
"minInt": 1,
"negPre": "\u00a4-",
"negSuf": "",
"negPre": "(\u00a4",
"negSuf": ")",
"posPre": "\u00a4",
"posSuf": ""
}
]
},
"id": "am",
"pluralCat": function (n, opt_precision) { var i = n | 0; if (i == 0 || n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
"pluralCat": function (n) { if (n == 0 || n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
});
}]);
+13 -13
View File
@@ -55,11 +55,11 @@ $provide.value("$locale", {
],
"fullDate": "EEEE\u060c d MMMM\u060c y",
"longDate": "d MMMM\u060c y",
"medium": "dd\u200f/MM\u200f/y h:mm:ss a",
"mediumDate": "dd\u200f/MM\u200f/y",
"medium": "dd\u200f/MM\u200f/yyyy h:mm:ss a",
"mediumDate": "dd\u200f/MM\u200f/yyyy",
"mediumTime": "h:mm:ss a",
"short": "d\u200f/M\u200f/y h:mm a",
"shortDate": "d\u200f/M\u200f/y",
"short": "d\u200f/M\u200f/yyyy h:mm a",
"shortDate": "d\u200f/M\u200f/yyyy",
"shortTime": "h:mm a"
},
"NUMBER_FORMATS": {
@@ -68,32 +68,32 @@ $provide.value("$locale", {
"GROUP_SEP": "\u066c",
"PATTERNS": [
{
"gSize": 3,
"lgSize": 3,
"gSize": 0,
"lgSize": 0,
"macFrac": 0,
"maxFrac": 3,
"minFrac": 0,
"minInt": 1,
"negPre": "-",
"negSuf": "",
"negPre": "",
"negSuf": "-",
"posPre": "",
"posSuf": ""
},
{
"gSize": 3,
"lgSize": 3,
"gSize": 0,
"lgSize": 0,
"macFrac": 0,
"maxFrac": 2,
"minFrac": 2,
"minInt": 1,
"negPre": "\u00a4\u00a0-",
"negSuf": "",
"negPre": "\u00a4\u00a0",
"negSuf": "-",
"posPre": "\u00a4\u00a0",
"posSuf": ""
}
]
},
"id": "ar-001",
"pluralCat": function (n, opt_precision) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n % 100 >= 3 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n % 100 >= 11 && n % 100 <= 99) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
"pluralCat": function (n) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n == (n | 0) && n % 100 >= 3 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n == (n | 0) && n % 100 >= 11 && n % 100 <= 99) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
});
}]);
+13 -13
View File
@@ -55,11 +55,11 @@ $provide.value("$locale", {
],
"fullDate": "EEEE\u060c d MMMM\u060c y",
"longDate": "d MMMM\u060c y",
"medium": "dd\u200f/MM\u200f/y h:mm:ss a",
"mediumDate": "dd\u200f/MM\u200f/y",
"medium": "dd\u200f/MM\u200f/yyyy h:mm:ss a",
"mediumDate": "dd\u200f/MM\u200f/yyyy",
"mediumTime": "h:mm:ss a",
"short": "d\u200f/M\u200f/y h:mm a",
"shortDate": "d\u200f/M\u200f/y",
"short": "d\u200f/M\u200f/yyyy h:mm a",
"shortDate": "d\u200f/M\u200f/yyyy",
"shortTime": "h:mm a"
},
"NUMBER_FORMATS": {
@@ -68,32 +68,32 @@ $provide.value("$locale", {
"GROUP_SEP": "\u066c",
"PATTERNS": [
{
"gSize": 3,
"lgSize": 3,
"gSize": 0,
"lgSize": 0,
"macFrac": 0,
"maxFrac": 3,
"minFrac": 0,
"minInt": 1,
"negPre": "-",
"negSuf": "",
"negPre": "",
"negSuf": "-",
"posPre": "",
"posSuf": ""
},
{
"gSize": 3,
"lgSize": 3,
"gSize": 0,
"lgSize": 0,
"macFrac": 0,
"maxFrac": 2,
"minFrac": 2,
"minInt": 1,
"negPre": "\u00a4\u00a0-",
"negSuf": "",
"negPre": "\u00a4\u00a0",
"negSuf": "-",
"posPre": "\u00a4\u00a0",
"posSuf": ""
}
]
},
"id": "ar-ae",
"pluralCat": function (n, opt_precision) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n % 100 >= 3 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n % 100 >= 11 && n % 100 <= 99) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
"pluralCat": function (n) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n == (n | 0) && n % 100 >= 3 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n == (n | 0) && n % 100 >= 11 && n % 100 <= 99) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
});
}]);
+13 -13
View File
@@ -55,11 +55,11 @@ $provide.value("$locale", {
],
"fullDate": "EEEE\u060c d MMMM\u060c y",
"longDate": "d MMMM\u060c y",
"medium": "dd\u200f/MM\u200f/y h:mm:ss a",
"mediumDate": "dd\u200f/MM\u200f/y",
"medium": "dd\u200f/MM\u200f/yyyy h:mm:ss a",
"mediumDate": "dd\u200f/MM\u200f/yyyy",
"mediumTime": "h:mm:ss a",
"short": "d\u200f/M\u200f/y h:mm a",
"shortDate": "d\u200f/M\u200f/y",
"short": "d\u200f/M\u200f/yyyy h:mm a",
"shortDate": "d\u200f/M\u200f/yyyy",
"shortTime": "h:mm a"
},
"NUMBER_FORMATS": {
@@ -68,32 +68,32 @@ $provide.value("$locale", {
"GROUP_SEP": "\u066c",
"PATTERNS": [
{
"gSize": 3,
"lgSize": 3,
"gSize": 0,
"lgSize": 0,
"macFrac": 0,
"maxFrac": 3,
"minFrac": 0,
"minInt": 1,
"negPre": "-",
"negSuf": "",
"negPre": "",
"negSuf": "-",
"posPre": "",
"posSuf": ""
},
{
"gSize": 3,
"lgSize": 3,
"gSize": 0,
"lgSize": 0,
"macFrac": 0,
"maxFrac": 2,
"minFrac": 2,
"minInt": 1,
"negPre": "\u00a4\u00a0-",
"negSuf": "",
"negPre": "\u00a4\u00a0",
"negSuf": "-",
"posPre": "\u00a4\u00a0",
"posSuf": ""
}
]
},
"id": "ar-bh",
"pluralCat": function (n, opt_precision) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n % 100 >= 3 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n % 100 >= 11 && n % 100 <= 99) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
"pluralCat": function (n) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n == (n | 0) && n % 100 >= 3 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n == (n | 0) && n % 100 >= 11 && n % 100 <= 99) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
});
}]);
-99
View File
@@ -1,99 +0,0 @@
'use strict';
angular.module("ngLocale", [], ["$provide", function($provide) {
var PLURAL_CATEGORY = {ZERO: "zero", ONE: "one", TWO: "two", FEW: "few", MANY: "many", OTHER: "other"};
$provide.value("$locale", {
"DATETIME_FORMATS": {
"AMPMS": [
"\u0635",
"\u0645"
],
"DAY": [
"\u0627\u0644\u0623\u062d\u062f",
"\u0627\u0644\u0627\u062b\u0646\u064a\u0646",
"\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621",
"\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621",
"\u0627\u0644\u062e\u0645\u064a\u0633",
"\u0627\u0644\u062c\u0645\u0639\u0629",
"\u0627\u0644\u0633\u0628\u062a"
],
"MONTH": [
"\u064a\u0646\u0627\u064a\u0631",
"\u0641\u0628\u0631\u0627\u064a\u0631",
"\u0645\u0627\u0631\u0633",
"\u0623\u0628\u0631\u064a\u0644",
"\u0645\u0627\u064a\u0648",
"\u064a\u0648\u0646\u064a\u0648",
"\u064a\u0648\u0644\u064a\u0648",
"\u0623\u063a\u0633\u0637\u0633",
"\u0633\u0628\u062a\u0645\u0628\u0631",
"\u0623\u0643\u062a\u0648\u0628\u0631",
"\u0646\u0648\u0641\u0645\u0628\u0631",
"\u062f\u064a\u0633\u0645\u0628\u0631"
],
"SHORTDAY": [
"\u0627\u0644\u0623\u062d\u062f",
"\u0627\u0644\u0627\u062b\u0646\u064a\u0646",
"\u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621",
"\u0627\u0644\u0623\u0631\u0628\u0639\u0627\u0621",
"\u0627\u0644\u062e\u0645\u064a\u0633",
"\u0627\u0644\u062c\u0645\u0639\u0629",
"\u0627\u0644\u0633\u0628\u062a"
],
"SHORTMONTH": [
"\u064a\u0646\u0627\u064a\u0631",
"\u0641\u0628\u0631\u0627\u064a\u0631",
"\u0645\u0627\u0631\u0633",
"\u0623\u0628\u0631\u064a\u0644",
"\u0645\u0627\u064a\u0648",
"\u064a\u0648\u0646\u064a\u0648",
"\u064a\u0648\u0644\u064a\u0648",
"\u0623\u063a\u0633\u0637\u0633",
"\u0633\u0628\u062a\u0645\u0628\u0631",
"\u0623\u0643\u062a\u0648\u0628\u0631",
"\u0646\u0648\u0641\u0645\u0628\u0631",
"\u062f\u064a\u0633\u0645\u0628\u0631"
],
"fullDate": "EEEE\u060c d MMMM\u060c y",
"longDate": "d MMMM\u060c y",
"medium": "dd\u200f/MM\u200f/y h:mm:ss a",
"mediumDate": "dd\u200f/MM\u200f/y",
"mediumTime": "h:mm:ss a",
"short": "d\u200f/M\u200f/y h:mm a",
"shortDate": "d\u200f/M\u200f/y",
"shortTime": "h:mm a"
},
"NUMBER_FORMATS": {
"CURRENCY_SYM": "\u00a3",
"DECIMAL_SEP": "\u066b",
"GROUP_SEP": "\u066c",
"PATTERNS": [
{
"gSize": 3,
"lgSize": 3,
"macFrac": 0,
"maxFrac": 3,
"minFrac": 0,
"minInt": 1,
"negPre": "-",
"negSuf": "",
"posPre": "",
"posSuf": ""
},
{
"gSize": 3,
"lgSize": 3,
"macFrac": 0,
"maxFrac": 2,
"minFrac": 2,
"minInt": 1,
"negPre": "\u00a4\u00a0-",
"negSuf": "",
"posPre": "\u00a4\u00a0",
"posSuf": ""
}
]
},
"id": "ar-dj",
"pluralCat": function (n, opt_precision) { if (n == 0) { return PLURAL_CATEGORY.ZERO; } if (n == 1) { return PLURAL_CATEGORY.ONE; } if (n == 2) { return PLURAL_CATEGORY.TWO; } if (n % 100 >= 3 && n % 100 <= 10) { return PLURAL_CATEGORY.FEW; } if (n % 100 >= 11 && n % 100 <= 99) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
});
}]);

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