Compare commits

...

632 Commits

Author SHA1 Message Date
Jeff Cross c54990ca6e docs(CHANGELOG.md): add changes for 1.3.0-rc.1 and 1.2.24 2014-09-09 15:45:51 -07:00
Shahar Talmi 3c538c1d21 feat(ngModelOptions): add allowInvalid option
This option allows to write invalid values to the model instead of having them become undefined.
Use this together with calling `ctrl.$setValidity` directly for displaying errors
from serverside validation.

Closes #8290
Closes #8313
2014-09-09 13:48:17 -07:00
Tobias Bosch 64c3b745fb fix(ngModel): update model value with async validators correctly
If the view value changed in the first digest and there are async validators,
the view value was never applied to the model after the validators were
resolved. Only important for tests.
2014-09-09 13:46:28 -07:00
Tobias Bosch f94d551529 fix(ngModel): render immediately also with async validators 2014-09-09 13:46:28 -07:00
Tobias Bosch 9ad7d745ab refactor(ngModel): remove $$invalidModelValue and refactor methods
- define `ngModelGet` and `ngModelSet` to already use
  the getter/setter semantics, so the rest of the code does
  not need to care about it.
- remove `ctrl.$$invalidModelValue` to simplify the internal logic
2014-09-09 13:46:24 -07:00
Igor Minar 90cd1e0a1b docs: add perf todo notes from #8515 2014-09-09 22:36:35 +02:00
Jason Bedard b3b476db7d perf($parse): remove getterFn wrapper for internal use
Closes #8901
2014-09-09 22:15:23 +02:00
Jason Bedard 456dcb020b test($parse): adding benchmark for execution of $parse()ed expressions
Part of #8901
2014-09-09 22:15:23 +02:00
Tobias Bosch 7235329ff8 docs(ngModel): update breaking change from 1.3.0-beta.11 to 1.3.0-beta.12
Closes #8357
2014-09-09 12:38:43 -07:00
Jeff Cross 06fa2868de revert: "fix($compile): render nested transclusion at the root of a template"
This reverts commit 6d1e7cdc51.

This commit was causing breakages because of its assumption that transcluded
content would be handled predictably, i.e. with ngTransclude, whereas many
use cases involve manipulating transcluded content in linking functions.
2014-09-09 11:05:34 -07:00
Chirayu Krishnappa bd8ad0fbe8 fix($parse): disallow passing Function to Array.sort
Fix the following exploit:

    hasOwnProperty.constructor.prototype.valueOf = valueOf.call;
    ["a", "alert(1)"].sort(hasOwnProperty.constructor);

The exploit:
• 1. Array.sort takes a comparison function and passes it 2 parameters to compare.
  2. It then calls .valueOf() if the result is not a primitive.
• The Function object conveniently accepts two string arguments so we can use this
  to construct a function.  However, this doesn't do much unless we can execute it.
• We set the valueOf function on Function.prototype to Function.prototype.call.
  This causes the function that we constructed to be executed when sort calls
  .valueOf() on the result of the comparison.

The fix is in two parts.
• Disallow passing unsafe objects to function calls as parameters.
• Do not traverse the Function object when setting a path.
2014-09-09 10:39:39 -07:00
Caitlin Potter 6639ca9d6b fix(ngInclude): correctly add svg-namespaced template content
It is now possible for ngInclude to correctly load SVG content in non-blink browsers, which do not
sort out the namespace when parsing HTML.

Closes #7538
Closes #8981
Closes #8997
2014-09-09 12:45:15 -04:00
Caitlin Potter 719f42e949 chore(.jshintrc): add jqLiteParseHTML to globals 2014-09-09 11:43:49 -04:00
Caitlin Potter 73916108f8 chore(.jshintrc): add jqLiteBuildFragment to globals 2014-09-09 11:43:49 -04:00
Igor Minar ed63733000 fix(ngRepeat): preserve original position of elements that are being animated away
During the recent refactoring a typo was made that broke code that detects if we are
already removed from the DOM (animation has completed).

Closes #8918
Closes #8994
2014-09-09 16:19:47 +02:00
Igor Minar f33a938545 chore(testabilityPatch): fix the dump fn so that it works with karma's debug.html 2014-09-09 16:19:47 +02:00
Igor Minar 01ef12884b test(animateSpec): remove unused variables 2014-09-09 16:19:46 +02:00
Igor Minar 732d72d991 test(ngRepeat): move an existing test into the right describe block 2014-09-09 16:19:46 +02:00
Peter Bacon Darwin 66103c8277 chore(npm-shrinkwrap): safely update karma to 0.12.23 2014-09-09 10:21:11 +01:00
Peter Bacon Darwin fee8f1c07b chore(npm-shrinkwrap): fix karma dependencies
Updating to karma 0.12.13 (in commit 408508ad29)
caused `iit` and `ddescribe` to crash and disconnect the browser stopping the
test run.

It appears that the problem is with one of the dependencies of karma rather
than karma itself. At least one of the karma dependencies updated in line
with karma's dependencies' semver specifications but subtly changed their
behaviour to break karma.  Possibly this is related to chokidar, glob,
minimatch or fsevents.
2014-09-09 10:14:15 +01:00
Tobias Bosch 6046e14bd2 refactor(ngModelController,formController): centralize and simplify logic
The previous logic for async validation in
`ngModelController` and `formController` was not maintainable:
- control logic is in multiple parts, e.g. `ctrl.$setValidity`
  waits for end of promises and continuous the control flow
  for async validation
- logic for updating the flags `ctrl.$error`, `ctrl.$pending`, `ctrl.$valid`
  is super complicated, especially in `formController`

This refactoring makes the following changes:
- simplify async validation: centralize control logic
  into one method in `ngModelController`:
  * remove counters `invalidCount` and `pendingCount`
  * use a flag `currentValidationRunId` to separate
    async validator runs from each other
  * use `$q.all` to determine when all async validators are done
- centralize way how `ctrl.$modelValue` and `ctrl.$invalidModelValue`
  is updated
- simplify `ngModelController/formCtrl.$setValidity` and merge
  `$$setPending/$$clearControlValidity/$$clearValidity/$$clearPending`
  into one method, that is used by `ngModelController` AND
  `formController`
  * remove diff calculation, always calculate the correct state anew,
    only cache the css classes that have been set to not
    trigger too many css animations.
  * remove fields from `ctrl.$error` that are valid and add private `ctrl.$$success`:
    allows to correctly separate states for valid, invalid, skipped and pending,
    especially transitively across parent forms.
- fix bug in `ngModelController`:
  * only read out `input.validity.badInput`, but not
    `input.validity.typeMismatch`,
    to determine parser error: We still want our `email`
    validator to run event when the model is validated.
- fix bugs in tests that were found as the logic is now consistent between
  `ngModelController` and `formController`

BREAKING CHANGE:
- `ctrl.$error` does no more contain entries for validators that were
  successful.
- `ctrl.$setValidity` now differentiates between `true`, `false`,
  `undefined` and `null`, instead of previously only truthy vs falsy.

Closes #8941
2014-09-08 15:10:02 -07:00
Tobias Bosch 2a5af502c5 docs($location): clarify guide regarding link handling
The trick with setting `<base href=".">` has not worked since Angular 1.2.0.
It is also misleading that it talks about `$routeProvider.otherwise`
which is not important in this case.

Related to #8869
Closes #8908
2014-09-08 10:40:20 -07:00
Jason Bedard 9bedeb3353 perf(extend): remove use of forEach to remove calls/closures/passing arguments
Closes #8898
2014-09-08 17:15:02 +02:00
Jason Bedard df9e60c8e7 feat(angular.forEach): add the array/object as the 3rd param like the native array forEach
Closes #7902
2014-09-08 17:06:16 +02:00
Igor Minar 41cec4d680 refactor(select): remove code duplication 2014-09-08 16:58:47 +02:00
Peter Bacon Darwin 0f3ea45d73 docs($filter): remove duplicate documentation of register method 2014-09-08 12:05:11 +01:00
Peter Bacon Darwin cddd48fe20 docs(form): move param tag outside of main description 2014-09-08 12:05:11 +01:00
Peter Bacon Darwin be3b62cd09 chore(bower): refactor bower usage
The gulp bower task in the docs app was never actually running since it couldn't
find the bower.json file and was silently failing. Updating to a newer bower
highlighted this issue.

This commit moves the docs app specific bower components into the docs folder.
There are only jquery and closure compiler related components in the project
folder now.

It also improves the gulp bower task to provide better feedback of progress
and errors.
2014-09-08 12:05:11 +01:00
Peter Bacon Darwin 40308e5935 chore(package.json): tidy up dependencies
Sorted dependencies into alphabetic order. If we can keep them like this
it will be much easier to keep track of version changes.

Updated bower and gulp to newer versions.
2014-09-08 12:05:11 +01:00
Jason Bedard f6aa1c5561 perf(jQuery): only trigger $destroy if a handler exists
Speeds up largetable destruction by 30% (500ms) when jQuery 2.1.1 is present.

Closes #8859
2014-09-07 23:56:11 +02:00
Jason Bedard 43c67ccd16 perf($parse): removing references to Parser/Lexer from parsed expressions
This allows the parser and lexer objects to get GC-ed once the expression
is parsed.

Part of #8901
2014-09-07 23:02:31 +02:00
Jason Bedard 1cfd49ddf0 refactor($parse): simplifying some while(true) loops
Part of #8901
2014-09-07 22:55:33 +02:00
Jason Bedard 907b8c1675 perf($parse): calculate array lengths once at start of loop
Part of #8901
2014-09-07 22:53:16 +02:00
Jason Bedard 432aa9e4e4 refactor($parse): adding function names for easier debugging
Part of #8901
2014-09-07 22:52:00 +02:00
Jason Bedard b95dabb881 refactor($parse): simplifying multi-statement execution
Part of #8901
2014-09-07 22:42:05 +02:00
Pawel Kozlowski 0f3adece3b refactor($http): simplify buildUrl function
Closes #8955
2014-09-05 20:21:00 -04:00
Shahar Talmi e322cd9b3b fix(ngModelOptions): do not trigger digest on setViewValue if debouncing
Note that this change means that anyone watching `$viewValue` will have to
wait for a new digest before they are aware that it has been updated.

Closes #8814
Closes #8850
Closes #8911
2014-09-05 20:15:34 +01:00
Caitlin Potter b3b672130d fix(ngAnimate): support removing classes from SVG elements when using jQuery
Fixes a regression in ngAnimate introduced in 2f4437b3, whereby SVG elements would not be able to
have classes removed by ngAnimate methods when jQuery was loaded (without also including libraries
which patch jQuery to support SVG elements, such as jquery-svgdom.js).

This fix exports jqLiteHasClass as a private method `$$hasClass` on the `angular` global object,
which enables ngAnimate to use this SVG-safe method for testing if the class is available.

Closes #8872
Closes #8893
2014-09-05 13:51:17 -04:00
Julie Ralph 8b5d33dab8 chore(tests): update Protractor to v1.2.0 2014-09-05 10:49:18 -07:00
Vitali Tsevan cbdaabfb59 fix(orderBy): allow arrayLike objects to be ordered
Closes #8944
2014-09-05 11:56:09 +01:00
Rouven Weßling 3471fedfbc refactor(indexOf) Remove a now unused copy of the indexOf function
This was missed in 300bffc4fe

Closes #8939
2014-09-05 10:23:52 +01:00
Jeff Cross c3a58a9f34 fix($location): don't call toString on null values 2014-09-04 17:16:11 -07:00
thorn0 99d95f1639 fix($location): remove an unused parameter of $location.url 2014-09-04 15:09:18 -07:00
John Reilly 48e66cff40 docs($location): update search description to include number param 2014-09-04 14:49:52 -07:00
Pawel Kozlowski adb5c6d6cc fix($location): allow numeric location setter arguments
Fixes #7054
2014-09-04 09:55:03 -07:00
Peter Bacon Darwin b01a03c1b9 docs(guide): add sortOrder to each page
Finally we can control the order of the guide pages
2014-09-04 16:49:25 +01:00
Peter Bacon Darwin 43e0dc2dfe chore(docs): enable page ordering by @sortOrder tag 2014-09-04 16:49:25 +01:00
Matias Niemelä 976da56d50 test(ngModel): add missing tests for ngMin/ngMax for date inputs 2014-09-04 11:46:05 -04:00
Matias Niemelä 088545c185 fix(ngModel): properly parse min/max date values as strings for date inputs
Due to the nature of how date objects are rendered when JSON.stringify
is called, the resulting string contains two sets of quotes surrounding
it. This commit fixes that issue.

Closes #6755
2014-09-04 11:45:59 -04:00
Matias Niemelä b350283503 fix(ngModel): revalidate the model when min/max expression values change for date inputs
Closes #6755
2014-09-04 11:45:53 -04:00
Matias Niemelä 25541c1f87 fix(ngModel): consider ngMin/ngMax values when validating number input types
With this fix ngModel will treat ngMin as a min error and ngMax as a max error.
This also means that when either of these two values is changed then ngModel will
revaliate itself.
2014-09-04 11:45:46 -04:00
Matias Niemelä 7b273a2c97 fix(ngModel): revalidate the model when min/max expression values change for number inputs
As of this fix if the max or min value is changed via scope or by another ngModel
then it will trigger the model containing the min/max attributes to revalidate itself.

Closes #2404
2014-09-04 11:45:36 -04:00
Peter Bacon Darwin 3952408cf1 chore(docs): improve searching by member
The keywords processor now also extracts the members (i.e. method, properties
and events) into its own search term property. These are then used in the lunr
search index with higher weighting that normal keywords to push services that
contain the query term as a member higher up the search results.

Closes #7661
2014-09-04 14:23:04 +01:00
Peter Bacon Darwin 02bada130e refact(ngSwitch): don't create extra function in for loop
Closes #8927
2014-09-04 13:17:21 +01:00
The Big Red Geek 712299c2a2 fix(ngSwitch): ensure correct iterator is passed to async function
Closes #8833
2014-09-04 12:49:14 +01:00
Peter Bacon Darwin 6d1e7cdc51 fix($compile): render nested transclusion at the root of a template
Closes #8914
Closes #8925
2014-09-04 12:30:09 +01:00
Peter Bacon Darwin 86c6be82e5 docs($http): clarify overriding of default transformations
Closes #8590
2014-09-04 12:28:18 +01:00
Smitha Milli ae952fbf0b fix(numberFilter): format numbers that round to zero as nonnegative
Previously when a negative number was rounded to 0 by the number filter
it would be formated as a negative number.  This means something like
{{ -0.01 | number: 1 }} would output -0.0.  Now it will ouput 0.0
instead.

Closes #8489
2014-09-03 14:59:53 -07:00
thorn0 73157b0a0b docs(docs.css): improve comma spacing in TOC on mobile 2014-09-03 13:57:49 -07:00
Juampy 0ee0ce18c1 docs($sce:unsafe): fix link to $sce docs
The second link to Strict Contextual Escaping (SCE) points to a 404.

Closes #8514
2014-09-03 16:31:06 -04:00
thorn0 7f87988e41 docs(README): fix 'Contribution guidelines' link
The current link leads to a page 'Building and Testing AngularJS'.
This same link is also included in the 'Building AngularJS' section
of the README where it's more relevant.
2014-09-03 13:24:56 -07:00
TLChan 9a09f1d96d docs(tutorial/step_05): improve formatting of code identifier
Closes #8557
2014-09-03 16:24:06 -04:00
Zach Pomerantz e96be5bfb8 docs(interpolate): fix link text 2014-09-03 13:17:46 -07:00
Vic Metcalfe 095627ad17 docs(ngBlur): explain blur events 2014-09-03 13:04:50 -07:00
thammin 1b4a2c8fee docs(ngSwitch): fix priority 2014-09-03 12:00:35 -07:00
Caitlin Potter b474c36e41 docs(CHANGELOG.md): add breaking change for a9fcb0d0 (v1.2.13)
Closes #8909
2014-09-03 13:13:25 -04:00
Jeff Cross 007e320835 chore(shrink-wrap): update shrinkwrap to latest benchpress 2014-09-03 09:22:13 -07:00
Tim Whitbeck f211419be6 docs(ngModelController): fix $asyncValidators example
Also fixes a typo (◜௰◝)

Closes #8906
2014-09-03 12:21:07 -04:00
Igor Minar 5dd9f138c7 chore(orderby-bp): fix the benchmark code and add jquery support 2014-09-03 16:37:46 +02:00
Peter Bacon Darwin 821da26e18 test($location): fix use of browserTrigger
You must now pass `keys` to the function in a config object.
This bug in the test became apparent because in newer browsers, arrays
have a function called `keys()` and this was causing browserTrigger to
fail. Previously it was quietly passing this test despite being wrong.
2014-09-03 14:56:49 +01:00
Rouven Weßling 300bffc4fe refactor(indexOf) use Array.prototype.indexOf exclusively
Replace helper functions with the native ES5 method

Closes #8847
2014-09-03 13:37:03 +01:00
thorn0 5b2a386b1f docs(jsdoc): remove @kind function for providers
This gets rid of the bizarre "Usage: fooProvider();" which does not really communicate anything useful.

Closes #8809
2014-09-03 08:32:15 -04:00
Shahar Talmi 953ee22f76 fix(ngForm): don't clear validity of whole form when removing control
Calling `$$clearControlValidity` on the parent of a nested form caused the parent form
to look like there are no more errors on the nested form even if it still had some
inputs with errors. there is no need to call this method recursively since `$setValidity`
will propagate the new validity state well enough.

Closes #8863
2014-09-03 13:30:33 +01:00
Shahar Talmi c3064f728c refactor(ngModel): get rid of revalidate
Since the validation was refactored we can now work out inside
`$commitViewValue()` whether to ignore validation by looking at whether
the input has native validators.

Closes #8856
2014-09-03 13:20:16 +01:00
The Big Red Geek 0f806d9659 refactor(ngSwitch): remove undocumented change attribute from ngSwitch
BREAKING CHANGE:

Ever since 0df93fd, tagged in v1.0.0rc1, the ngSwitch directive has had an undocumented `change`
attribute, used for evaluating a scope expression when the switch value changes.

While it's unlikely, applications which may be using this feature should work around the removal
by adding a custom directive which will perform the eval instead. Directive controllers are
re-instantiated when being transcluded, so by putting the attribute on each item that you want
to be notified of a change to, you can more or less emulate the old behaviour.

Example:

```js
angular.module("switchChangeWorkaround", []).
  directive("onSwitchChanged", function() {
    return {
      linke: function($scope, $attrs) {
        $scope.$parent.$eval($attrs.change);
      }
    };
  });
```

```html
<div ng-switch="switcher">
  <div ng-switch-when="a" on-switch-changed="doSomethingInParentScope()"></div>
  <div ng-switch-when="b" on-switch-changed="doSomethingInParentScope()"></div>
</div>
```

Closes #8858
Closes #8822
2014-09-03 07:38:11 -04:00
Peter Bacon Darwin ac535549c9 chore(package.json): update to dgeni-packages v0.9.8
Closes #8860
2014-09-03 11:38:44 +01:00
Leonardo Zizzamia d9cdb105fc test(orderBy): implement benchmark for ngRepeat with orderBy 2014-09-02 15:21:36 -07:00
Brian Ford 44cf2e1904 style(ngModel): fix indentation 2014-09-02 14:51:16 -07:00
Nicolai Skogheim ce25ac83b4 docs(ngRepeat): update step_02.ngdoc with challenge
Add a simple task for the user to better understand ng-repeat.

Close #8757
2014-09-02 16:46:01 -04:00
Shahar Talmi d2d8117edd docs($rootScope): document scope properties 2014-09-02 13:35:17 -07:00
Tiago Ribeiro 63fb60de86 docs(changelog): fix inline formatting 2014-09-02 13:01:41 -07:00
Nima Mehanian 29714a34ab docs(guide/providers): fix grammar and punctuation 2014-09-02 12:43:28 -07:00
Brian Ford d5686ffc48 style(ngModel): fix spacing 2014-09-02 12:10:23 -07:00
Shahar Talmi 203ea10f9e fix(ngEventDirs): check scope.$$phase only on $rootScope
Closes #8891, #8849
2014-09-02 10:42:01 -07:00
Shahar Talmi bf59d7274f fix(input): check scope.$$phase only on $rootScope 2014-09-02 10:41:32 -07:00
Tobias Bosch 995a8d39af docs(errors): fix base href in $location:nobase error page 2014-09-02 10:21:41 -07:00
Tobias Bosch fc706d13d8 fix($location): set baseHref in mock browser to /
Set the default value for the base tag in the mock browser to `/`,
as we now always require a base tag to be present for html5 mode.

Fixes #8866
Closes #8889
2014-09-02 09:54:46 -07:00
Peter Bacon Darwin 9525d0ad1d docs($compile): clarify linking when there are templateUrl directives
Closes #8877
Closes #8631
2014-09-02 15:37:29 +01:00
Caitlin Potter e0d49a3109 refactor(ngRepeat): specify explicit false for cloneNode deepClone parameter
This should provide a slight compat improvement for old versions of Opera, which did not treat the
`false` as the default value.

There is no test for this fix as Opera 11 is not a browser which runs on the CI servers.

Closes #8883
Closes #8885
2014-09-02 03:04:00 -04:00
Caitlin Potter c5b32f14d5 docs(CHANGELOG.md): add breaking change from 5f3f25a1
5f3f25a1 included a breaking change which was not documented, which is that the return value of directive
constructors is ignored. The reason they are ignored is to ensure that the correct object is bound to when
binding properties to the controller. It may be possible to come up with a better solution which informs
the developer that what they are doing is wrong, rather than just breaking instead.

Closes #8876
Closes #8882
2014-09-01 18:15:57 -04:00
Igor Minar 2e0982c1ec docs(errors): fix link in the $location:nobase error page 2014-08-31 11:03:59 -07:00
Igor Minar b2902446eb chore(travis): move docse2e tests into the unit tests vm
we spend more time making getting the build ready than running the docs e2e tests.

by piggy-backing on unit tests we'll finish the build faster
2014-08-29 21:54:32 -07:00
Matias Niemelä 202aed7770 docs(changelog): release notes for 1.3.0-RC.0 sonic-boltification 2014-08-29 21:22:46 -04:00
Tobias Bosch 271572c20e fix(docs): only check for SEVERE logs in tests 2014-08-29 17:57:23 -07:00
Igor Minar 550ba01b32 fix(docs): don't throw exception on the 404 page
Closes #8518
2014-08-29 16:13:11 -07:00
Tobias Bosch 22948807e3 fix($location): always resolve relative links in html5mode to <base> url
BREAKING CHANGE (since 1.2.0 and 1.3.0-beta.1):

Angular now requires a `<base>` tag when html5 mode of `$location` is enabled. Reasoning:
Using html5 mode without a `<base href="...">` tag makes relative links for images, links, ...
relative to the current url if the browser supports
the history API. However, if the browser does not support the history API Angular falls back to using the `#`,
and then all those relative links would be broken.

The `<base>` tag is also needed when a deep url is loaded from the server, e.g. `http://server/some/page/url`.
In that case, Angular needs to decide which part of the url is the base of the application, and which part
is path inside of the application.

To summarize: Now all relative links are always relative to the `<base>` tag.

Exception (also a breaking change):
Link tags whose `href` attribute starts with a `#` will only change the hash of the url, but nothing else
(e.g. `<a href="#someAnchor">`). This is to make it easy to scroll to anchors inside a document.

Related to #6162
Closes #8492

BREAKING CHANGE (since 1.2.17 and 1.3.0-beta.10):

In html5 mode without a `<base>` tag on older browser that don't support the history API
relative paths were adding up. E.g. clicking on `<a href="page1">` and then on `<a href="page2">`
would produce `$location.path()==='/page1/page2'. The code that introduced this behavior was removed
and Angular now also requires a `<base>` tag to be present when using html5 mode.

Closes #8172, #8233
2014-08-29 15:19:51 -07:00
Tobias Bosch b9007df590 refactor(locationSpec): make helper functions take an object
Makes tests more readable
2014-08-29 15:05:50 -07:00
Smitha Milli 0604bb7b7a fix(ngRepeat): improve errors for duplicate items
-Log the value that had the duplicate key, as well as the key
The error that is thrown when items have duplicate track by keys can be
confusing because only the duplicate key is logged.  If the user didn't
provide that key themselves, they may not know what it is or what item
it corresponds to.
2014-08-29 13:46:37 -07:00
Matias Niemelä 92576743ee fix($animate): wait two until two digests are over until enabling animations
Even when no remote templates are to be downloaded, wait until the end of the
post digest queue before enabling animations since all $animate-triggered
animation events perform a post digest before running animations.

Closes #8844
2014-08-29 16:17:32 -04:00
Matias Niemelä c9b0bfecc9 fix(ngSwitch): avoid removing DOM nodes twice within watch operation
Closes #8662
2014-08-29 15:58:13 -04:00
Igor Minar 2ae10f67fc fix(numberFilter): pass through null and undefined values
When these special values are passed through one-time binding will work correctly.

BREAKING CHANGE: previously the number filter would convert null and undefined values into empty string, after this change
these values will be passed through.

Only cases when the number filter is chained with another filter that doesn't expect null/undefined will be affected. This
should be very rare.

This change will not change the visual output of the filter because the interpolation will convert the null/undefined to
an empty string.

Closes #8605
Closes #8842
2014-08-29 12:33:43 -07:00
Igor Minar c2aaddbe4b fix(currencyFilter): pass through null and undefined values
When these special values are passed through one-time binding will work correctly.

BREAKING CHANGE: previously the currency filter would convert null and undefined values into empty string, after this change
these values will be passed through.

Only cases when the currency filter is chained with another filter that doesn't expect null/undefined will be affected. This
should be very rare.

This change will not change the visual output of the filter because the interpolation will convert the null/undefined to
an empty string.

Closes #8605
2014-08-29 12:32:51 -07:00
Wesley Cho 6f7018d52f perf(select): execute render after $digest cycle
This is an optimization to defer execution of the render function in the
select directive after the $digest cycle completes inside the
$watchCollection expressions.  This does a check to see if the render
function is already registered in the $$postDigestQueue before it passes
it into $$postDigest, guaranteeing that the DOM manipulation happens
only in one execution after the model settles.

Closes #8825
2014-08-29 12:24:49 -07:00
Michael Barton 4f9ac078d5 docs($rootScope): remove duplicate $digest()
Closes #8840
2014-08-29 14:38:08 -04:00
zahragh 9057ed21ac docs(FormController): document $submitted property
Closes #8732
2014-08-29 14:35:22 -04:00
danrbergman c09f619318 docs($q): fixed spelling, removed extra characters
Closes #8779
2014-08-29 14:00:50 -04:00
Matias Niemelä 1eda18365a fix(ngModel): always format the viewValue as a string for text, url and email types
NgModel will format all scope-based values to string when setting the viewValue for
the associated input element. The formatting, however, only applies to input elements
that contain a text, email, url or blank input type. In the event of a null or undefined
scope or model value, the viewValue will be set to null or undefined instead of being
converted to an empty string.
2014-08-29 13:29:47 -04:00
Caitlin Potter 77ce5b89f9 fix(input): validate minlength/maxlength for non-string values
Use the viewValue rather than modelValue when validating. The viewValue should always be a string, and
should reflect what the user has entered, or the formatted model value.

BREAKING CHANGE:

Always uses the viewValue when validating minlength and maxlength.

Closes #7967
Closes #8811
2014-08-29 13:20:03 -04:00
Caitlin Potter c5f1ca3d91 chore(compare-master-to-stable): make checks for bugfixes better
Prevent the script from alerting you if a docs fix has something like "Fixes typo in foo", which is
not how bugfixes are worded.

Closes #8801
2014-08-29 11:59:07 -04:00
Sekib Omazic 7a36d49533 docs($filter): Date filter am/pm case
Use uppercase for AM/PM in date filter

fixes #8763
2014-08-29 13:04:05 +02:00
rodyhaddad cd21602d5b fix(ngBindHtml): throw error if interpolation is used in expression
Closes #8824
2014-08-29 01:24:46 -04:00
Caitlin Potter 5f3f25a1a6 feat($compile): bind isolate scope properties to controller
It is now possible to ask the $compiler's isolate scope property machinery to bind isolate
scope properties to a controller rather than scope itself. This feature requires the use of
controllerAs, so that the controller-bound properties may still be referenced from binding
expressions in views.

The current syntax is to prefix the scope name with a '@', like so:

    scope: {
        "myData": "=someData",
        "myString": "@someInterpolation",
        "myExpr": "&someExpr"
    },
    controllerAs: "someCtrl",
    bindtoController: true

The putting of properties within the context of the controller will only occur if
controllerAs is used for an isolate scope with the `bindToController` property of the
directive definition object set to `true`.

Closes #7635
Closes #7645
2014-08-28 20:46:52 -07:00
Tobias Bosch cb73a37c7c fix($compile): use the correct namespace for transcluded svg elements
This fixes the case when a directive that uses `templateUrl`
is used inside of a transcluding directive like `ng-repeat`.

Fixes #8808
Closes #8816
2014-08-28 17:34:11 -07:00
Guilbert 49455a75dc docs(filterFilter): add note on negation 2014-08-28 14:55:53 -07:00
Julie 85880a6490 feat(testability): add $$testability service
The $$testability service is a collection of methods for use when debugging
or by automated testing tools. It is available globally through the function
`angular.getTestability`.
For reference, see the Angular.Dart version at
https://github.com/angular/angular.dart/pull/1191
2014-08-28 14:25:50 -07:00
Colin Casey 46343c603d feat(filterFilter): pass index to function predicate
Closes #654
2014-08-28 12:34:42 -07:00
Erin Altenhof-Long 3b5d75c021 feat(ngRoute): alias string as redirectTo property in .otherwise()
Allow `.otherwise()` to interpret a string parameter
as the `redirectTo` property

Closes #7794
2014-08-28 11:58:31 -07:00
Tobias Bosch 719c747cd8 fix(ngEventDirs): execute blur and focus expression using scope.$evalAsync
BREAKING CHANGE:
The `blur` and `focus` event fire synchronously, also during DOM operations
that remove elements. This lead to errors as the Angular model was not
in a consistent state. See this [fiddle](http://jsfiddle.net/fq1dq5yb/) for a demo.

This change executes the expression of those events using
`scope.$evalAsync` if an `$apply` is in progress, otherwise
keeps the old behavior.

Fixes #4979
Fixes #5945
Closes #8803
Closes #6910
Closes #5402
2014-08-28 11:49:31 -07:00
Tim Kindberg 2137542e09 docs(ngModelOptions): fix example 2014-08-28 11:36:22 -07:00
Shahar Talmi ab878a6c03 fix(ngModel): allow non-assignable binding when getterSetter is used
Closes #8704
2014-08-28 11:25:03 -07:00
Igor Minar 474a0337bd chore(benchmarks): disable debugInfo in largetable benchmark 2014-08-28 09:31:02 -07:00
Matias Niemelä 97a1b399b7 test($animate): add tests for noop enaled and cancel methods 2014-08-28 11:31:21 -04:00
Brian Ford c6bde52006 docs(debugInfo): add docs for $compileProvider.debugInfoEnabled() 2014-08-27 20:45:59 -07:00
Vojta Jina 563be7e879 refactor(ngBind): name link and compile functions
For easier debugging.
2014-08-27 20:45:59 -07:00
Vojta Jina e0489abd8d perf($compile): add debug classes in compile phase
In a93f03d and d37f103 we changed the compiler and ngBind to add debugging CSS classes (i.e. ng-scope, ng-binding) in linking function. This simplified the code and made sense under the original assumptions that the debug info will be disabled by default. That is however not the case - debug info is enabled by default.

When debug info is enabled, this change improves the largetable-bp
benchmark by ~580ms, that is 30% faster.
Measuring the “create” phase, 25 loops, meantime ~1920ms -> ~1340ms.

This change does not affect performance when debug info is disabled.
2014-08-27 20:45:59 -07:00
Vojta Jina 2218e6f8cd refactor($compile): rename element -> $element
To follow our convention (at least in this file): if it’s
a jqLite/jQuery wrapper than the variable name starts with `$`.
2014-08-27 20:45:59 -07:00
Vojta Jina cec9ecf951 refactor($compile): $$addScopeInfo always expects jq wrapper
`$$addScopeInfo` used to accept either DOM Node or jqLite/jQuery
wrapper. This commit simplifies the method to always require
jqLite/jQuery wrapper and thus remove the `element.data` condition which
was wrong. If `element` was a raw comment element, the `data` property
was a string (the value of the comment) and an exception was thrown.
2014-08-27 20:45:59 -07:00
Vojta Jina 36a547b852 refactor: remove doReload arg used only for testing
We run unit tests in “strict” mode and thus can’t monkey-patch `window.location` nor `window.location.reload`. In order to avoid full page reload, we could pass location as argument, or another level of indirection, something like this:
```js
var ourGlobalFunkyLocation = window.location;
function reloadWithDebugInfo() {
  window.name = 'NG_ENABLE_DEBUG_INFO!' + window.name;
  ourGlobalFunkyLocation.reload();
}

// in the test
ourGlobalFunkyLocation = {
  reload: function() {}
};
reloadWithDebugInfo();
ourGlobalFunkyLocation = window.location;
```

I don’t think any of these make sense, just so that we can test setting `window.name`. If the `reloadWithDebugInfo` function was more complicated, I would do it.

I don’t think it’s worthy to confuse production code with extra logic which purpose was only to make testing possible.
2014-08-27 20:45:59 -07:00
Vojta Jina b3ec730c42 refactor($compile): $$addBindingInfo accepts single expression or an array
Instead of knowing about `.expressions` property, it just accepts a single expression or an array of expressions.
2014-08-27 20:45:58 -07:00
Peter Bacon Darwin 2ab0d5d370 test(e2e): fix by.binding() locators
After upgrading, Protractor requires exact string that is used in the binding.
2014-08-27 20:45:58 -07:00
Vojta Jina ac68ee49c1 chore(deps): update protractor to 1.1.1 2014-08-27 20:45:58 -07:00
Peter Bacon Darwin be8ef25a5a chore(clean-shrinkwrap): chokidar is fixed since 0.8.2 2014-08-27 20:45:58 -07:00
Peter Bacon Darwin 41c1b8858f feat: add angular.reloadWithDebugInfo() 2014-08-27 20:45:58 -07:00
Vojta Jina fce8915f39 test(ngClass): dealoc elements 2014-08-27 20:45:58 -07:00
Vojta Jina d4dd5dfa18 test(input): dealoc elements 2014-08-27 20:45:58 -07:00
Peter Bacon Darwin a1e5cd5fe3 feat($compile): allow disabling scope info
The compiler adds scope information (`ng-scope` CSS class and `$scope` data property) to elements
when the are bound to the scope. This is mostly to aid debugging tools such as Batarang. In
production this should be unnecesary and adds a performance penalty.

In the bench/apps/largetable-bp this change caused an improvement of ~100ms (7%).

This can be now disabled by calling `$compileProvider.debugInfoEnabled(false)`
in a module `config` block:
```
someModule.config(['$compileProvider', function($compileProvider) {
  $compileProvider.debugInfoEnabled(false);
}]);
```

In the bench/apps/largetable-bp benchmark this change, with debug info disabled,
improved by ~120ms, that is ~10%.
Measuring the "create" phase, 25 loops, mean time ~1200ms -> ~1080ms.
2014-08-27 20:45:58 -07:00
Peter Bacon Darwin 3660fd0912 feat($compile/ngBind): allow disabling binding info
The compiler and ngBind directives add binding information (`ng-binding`
CSS class and `$binding` data property) to elements when they are bound to
the scope. This is only to aid testing and debugging for tools such as
Protractor and Batarang. In production this is unnecessary and add a
performance penalty.

This can be now disabled by calling `$compileProvider.debugInfoEnabled(false)`
in a module `config` block:
```
someModule.config(['$compileProvider', function($compileProvider) {
  $compileProvider.debugInfoEnabled(false);
}]);
```

In the bench/apps/largetable-bp benchmark this change, with debug info disabled,
improved by ~140ms, that is 10%.
Measuring the "create" phase, 25 loops, mean time ~1340ms -> ~1200ms.

We were storing the whole `interpolationFn` in the `$binding` data on
elements but this function was bringing a lot of closure variables with it
and so was consuming unwanted amounts of memory.

Now we are only storing the parsed interpolation expressions from the
binding (i.e. the values of `interpolationFn.expressions`).

BREAKING CHANGE:
The value of `$binding` data property on an element is always an array now
and the expressions do not include the curly braces `{{ ... }}`.
2014-08-27 20:45:58 -07:00
Matias Niemelä 4bca4c44b9 fix($animate): ensure guarded animations consider AJAX requests upon bootstrap
Prior to this fix when an Angular application is bootstrapped it would only
place an animation guard to prevent animations from running when the application
starts for the first two digest cycles. However, if any controllers or directives,
that are executed upon boostrap, trigger any remote code to be downloaded (via $http)
then the guard does not put that into consideration. This fix now properly addresses
that circumstance and removes the guard once all outbound HTTP requests are complete
when an Angular application is bootstrapped.

Closes #8275
Closes #5262
2014-08-27 23:19:29 -04:00
Matias Niemelä a70e2833ea feat($templateRequest): introduce the $templateRequest service
This handy service is designed to download and cache template contents
and to throw an error when a template request fails.

BREAKING CHANGE

Angular will now throw a $compile minErr each a template fails to download
for ngView, directives and ngMessage template requests. This changes the former
behavior of silently ignoring failed HTTP requests--or when the template itself
is empty. Please ensure that all directive, ngView and ngMessage code now properly
addresses this scenario. NgInclude is uneffected from this change.
2014-08-27 23:19:19 -04:00
Tobias Bosch 3be00df495 fix($browser): detect changes to the browser url that happened in sync
Closes #6976.
2014-08-27 16:36:53 -07:00
Zach Pomerantz 2efe1c2e7b docs(compile): translcuded -> transcluded
Oops.

Closes #8799
2014-08-27 17:14:44 -04:00
Igor Minar d8a02f9987 chore(build): uprade closure-compiler to v20140814
no significant change in code size
2014-08-27 13:57:36 -07:00
Igor Minar a4520a745d fix(Angular): remove duplicate nodeName_ references
I forgot to remove the variable declaration in previous nodeName_ commit.
2014-08-27 13:56:13 -07:00
Richard Harrington fe697527b4 docs(shallowCopy): add missing word 'are' and period.
Closes #8794
2014-08-27 08:38:35 -04:00
Caitlin Potter ea6fc6e69c feat($http): implement mechanism for coalescing calls to $apply in $http
When multiple responses are received within a short window from each other, it can be wasteful to
perform full dirty-checking cycles for each individual response. In order to prevent this, it is
now possible to coalesce calls to $apply for responses which occur close together.

This behaviour is opt-in, and the default is disabled, in order to avoid breaking tests or
applications.

In order to activate coalesced apply in tests or in an application, simply perform the following
steps during configuration.

   angular.module('myFancyApp', []).
     config(function($httpProvider) {
       $httpProvider.useApplyAsync(true);
     });

OR:

   angular.mock.module(function($httpProvider) {
     $httpProvider.useApplyAsync(true);
   });

Closes #8736
Closes #7634
Closes #5297
2014-08-26 21:42:47 -04:00
Caitlin Potter e94d454b84 feat($rootScope): implement $applyAsync to support combining calls to $apply into a single digest.
It is now possible to queue up multiple expressions to be evaluated in a single digest using
$applyAsync. The asynchronous expressions will be evaluated either 1) the next time $apply or
$rootScope.$digest is called, or 2) after after the queue flushing scheduled for the next turn
occurs (roughly ~10ms depending on browser and application).
2014-08-26 21:33:44 -04:00
Matias Niemelä 2ae4f40be1 feat(ngModel): provide validation API functions for sync and async validations
This commit introduces a 2nd validation queue called `$asyncValidators`. Each time a value
is processed by the validation pipeline, if all synchronous `$validators` succeed, the value
is then passed through the `$asyncValidators` validation queue. These validators should return
a promise. Rejection of a validation promise indicates a failed validation.
2014-08-26 18:31:01 -04:00
Matias Niemelä db044c408a fix(ngModel): treat undefined parse responses as parse errors
With this commit, ngModel will now handle parsing first and then validation
afterwards once the parsing is successful. If any parser along the way returns
`undefined` then ngModel will break the chain of parsing and register a
a parser error represented by the type of input that is being collected
(e.g. number, date, datetime, url, etc...). If a parser fails for a standard
text input field then an error of `parse` will be placed on `model.$error`.

BREAKING CHANGE

Any parser code from before that returned an `undefined` value
(or nothing at all) will now cause a parser failure. When this occurs
none of the validators present in `$validators` will run until the parser
error is gone.
2014-08-26 18:30:53 -04:00
Igor Minar 0e44ac2de0 refactor(hashKey): don't generate memory garbage
we now store both the object type and the id as the hashkey and return it for all objects.

for primitives we still have to do string concatination because we can't use expandos on them to
store the hashkey
2014-08-26 15:00:35 -07:00
Igor Minar 5a1a0c9622 perf(nodeName_): simplify the code and reduce the number of DOM calls 2014-08-26 15:00:35 -07:00
Igor Minar 4ebbd7e210 refactor(nodeName_): remove IE8 specific branch 2014-08-26 15:00:34 -07:00
Tobias Bosch 5f90340abb fix(input): allow to use seconds in input[time] and input[datetime-local]
The HTML5 spec allows to use seconds for `input[time]` and `input[datetime-local]`,
even though they are not displayed by all browsers.

Related to #8447.
2014-08-26 14:21:05 -07:00
Tobias Bosch cc6fc199f5 feat(input): allow to define the timezone for parsing dates
Angular used to always use the browser timezone when parsing
`input[date]`, `input[time]`, … The timezone can now be changed
to `UTC` via `ngModelOptions`.

Closes #8447.
2014-08-26 14:21:02 -07:00
Tobias Bosch 29f0b568de fix(input): use year 1970 instead of 1900 for input[time]
BREAKING CHANGE:

According to the HTML5 spec `input[time]` should create dates
based on the year 1970 (used to be based on the year 1900).

Related to #8447.
2014-08-26 14:20:55 -07:00
Tobias Bosch 4739b1d9da feat(filter): allow to define the timezone for formatting dates
Angular used to always use the browser timezone for
`dateFilter`. An additional parameter was added to allow to use
`UTC` timezone instead.

Related to #8447.
2014-08-26 14:20:49 -07:00
Tobias Bosch feed7d6944 chore(tests): use jquery again in e2e tests
jQuery was not included in e2e tests, but we did not notice it
as Angular fell back to jqlite…
2014-08-26 14:19:25 -07:00
Caitlin Potter 9da8d63ef4 docs($q): correct @ngdoc annotations for methods of $q
Closes #8782
Closes #8784
2014-08-26 17:11:37 -04:00
Jeff Cross 0462b688f9 chore($q): replace plain TypeError with minErr+TypeError in cyclical resolve check 2014-08-26 12:33:51 -07:00
Jeff Cross 1b331f3729 chore($q): convert thrown Error to $minErr when calling $q constructor without resolver 2014-08-26 12:09:26 -07:00
Jeff Cross a6bd4bc866 feat(minErr): allow specifying ErrorConstructor in minErr constructor
In some cases, the type of Error thrown by minErr is meaningful, such as in $q where a TypeError
is sometimes required. This fix allows providing an error constructor as the second argument to
minErr, which will be used to construct the error that gets returned by the factory function.
2014-08-26 12:09:26 -07:00
Matias Niemelä 23da614043 fix($animate): use $timeout to handle the delay within staggering animations
When transition-delay and animation-delay were used to drive the staggering
animation the result was unpredictable at times due to the browser not being
able to register the generated delay styles in time. This caused a hard to
track down bug that didn't have a solid solution when styles were being used.

This fix ensures that stagger delays are handled by the $timeout service.

Closes #7228
Closes #7547
Closes #8297
Closes #8547

BREAKING CHANGE

If any stagger code consisted of having BOTH transition staggers and delay staggers
together then that will not work the same way. Angular will now instead choose
the highest stagger delay value and set the timeout to wait for that before
applying the active CSS class.
2014-08-26 11:45:00 -04:00
Matias Niemelä bf0f5502b1 feat($animate): use promises instead of callbacks for animations
The $animate service (both the service inside of ng and ngAnimate) now
makes use of promises instead of callback functions.

BREAKING CHANGE

Both the API for the cancallation method and the done callback for
$animate animations is different. Instead of using a callback function
for each of the $animate animation methods, a promise is used instead.

```js
//before
$animate.enter(element, container, null, callbackFn);

//after
$animate.enter(element, container).then(callbackFn);
```

The animation can now be cancelled via `$animate.cancel(promise)`.

```js
//before
var cancelFn = $animate.enter(element, container);
cancelFn(); //cancels the animation

//after
var promise = $animate.enter(element, container);
$animate.cancel(promise); //cancels the animation
```
2014-08-26 11:44:25 -04:00
Matias Niemelä 2f4437b3a1 feat($animate): coalesce concurrent class-based animations within a digest loop
All class-based animation methods (addClass, removeClass and setClass) on $animate
are now processed after the next digest occurs. This fix prevents any sequencing
errors from occuring from excessive calls to $animate.addClass, $animate.remoteClass
or $animate.setClass.

BREAKING CHANGE

$animate.addClass, $animate.removeClass and $animate.setClass will no longer start the animation
right after being called in the directive code. The animation will only commence once a digest
has passed. This means that all animation-related testing code requires an extra digest to kick
off the animation.

```js
//before this fix
$animate.addClass(element, 'super');
expect(element).toHaveClass('super');

//now
$animate.addClass(element, 'super');
$rootScope.$digest();
expect(element).toHaveClass('super');
```

$animate will also tally the amount of times classes are added and removed and only animate
the left over classes once the digest kicks in. This means that for any directive code that
adds and removes the same CSS class on the same element then this may result in no animation
being triggered at all.

```js
$animate.addClass(element, 'klass');
$animate.removeClass(element, 'klass');

$rootScope.$digest();

//nothing happens...
```
2014-08-26 11:43:18 -04:00
Matias Niemelä d0b41890bf chore(ngAnimate): fix if statement whitespacing 2014-08-26 10:29:47 -04:00
grsmvg 7ef2921cae docs(form): add dollar sign back to setSubmitted()
Dollar sign was missing for setSubmitted() due to fc73256464, just
adding it back in ヽ(^。^)ノ

Closes #8772
2014-08-26 03:58:54 -04:00
Richard Harrington 5e15b11509 refactor($injector): remove unused strictDi argument from createInternalInjector
createInternalInjector does not specify the formal parameter `strictDi`, and instead uses the binding
from the parent function's formal parameters, making this parameter unnecessary.

Closes #8771
2014-08-26 01:37:44 -04:00
dennishall1 42f28751e0 docs(dateFilter): add example of string literals in format string
Also changes the wording to include the word "escaped" and "escape", which may help users find the
information they're looking for via searching. (ノ◕ヮ◕)ノ*:・゚✧

Closes #8770
2014-08-25 23:16:21 -04:00
Akhlesh b728030be0 docs(guide/directive): update since 'EA' is now the default restrict value
11f5aeeee9 changed the compiler to use 'EA' as a 'restrict'
value if not specified in the directive object, and the directive guide needed some slight
changes to address this.

Closes #8769
2014-08-25 22:53:08 -04:00
vdyckn 2e3a7fd3e9 docs(guide/directive) example79 ptor missing attr
Closes #8257
2014-08-25 12:28:33 -07:00
Jason Bedard fdf9989f7c perf($compile): only iterate over elements with link functions
Closes #8741
2014-08-25 11:02:48 -07:00
Richard Harrington addfc567fd refactor($injector): remove unused invoke queue variable
Closes #8755
2014-08-24 19:14:20 +02:00
Smith a9371a1875 docs(guide/di): correct spelling behinds > behind
Closes #8749
2014-08-23 16:37:07 -04:00
Pawel Kozlowski 8ac90357a6 fix($parse): properly handle dots at the end of identifiers
Fixes #4613
Fixes #4912
Closes #8559
2014-08-23 11:38:24 +02:00
Peter Bacon Darwin 525a8f851e docs($compile): fix grammar and specify version for deprecation 2014-08-23 07:07:38 +01:00
Brian Ford fc8d6d75ab docs(changelog): release notes for 1.2.23 superficial-malady 2014-08-22 15:57:26 -07:00
Brian Ford b93601e691 docs(changelog): release notes for 1.3.0-beta.19 rafter-ascension 2014-08-22 15:57:26 -07:00
Igor Minar 1a2caad922 chore(mocks): remove helper fn angular.mocks.clearData
we don't need this any more because Karma reloads the iframe after each test run

Related to #8532
Closes #8618
2014-08-22 15:30:34 -07:00
Tobias Bosch ffbd276d6d fix($compile): use the correct namespace for transcluded svg elements
Via transclusion, svg elements can occur outside an `<svg>` container in an
Angular template but are put into an `<svg>` container through compilation
and linking.

E.g.
Given that `svg-container` is a transcluding directive with
the following template:
```
<svg ng-transclude></svg>
```

The following markup creates a `<circle>` inside of an `<svg>` element
during runtime:
```
<svg-container>
  <circle></circle>
</svg-container>
```

However, this produces non working `<circle>` elements, as svg elements
need to be created inside of an `<svg>` element.

This change detects for most cases the correct namespace of transcluded content
and recreates that content in the correct `<svg>` container
when needed during compilation. For special cases it adds an addition argument
to `$transclude` that allows to specify the future parent node of elements
that will be cloned and attached using the `cloneAttachFn`.

Related to #8494
Closes #8716
2014-08-22 14:02:13 -07:00
Tobias Bosch 75c4cbf81f refactor($compile): rename directive.type to directive.templateNamespace
Also corrects the tests for MathML that use `directive.templateNamespace`.

BREAKING CHANGE (within 1.3.0-beta): `directive.type` was renamed to `directive.templateNamespace`

The property name `type` was too general.
2014-08-22 14:00:58 -07:00
Shahar Talmi 642af96c48 refactor(Angular): make NaN check in date equality cleaner
Closes #8718
2014-08-22 13:52:06 -07:00
Igor Minar 252e8b5733 revert: feat($compile): bind isolate scope properties to controller
This reverts commit 787c5a76dc.

This change causes a regression at Google. We'll take a better look at it
next week.

Reopens #7645
2014-08-22 11:48:29 -07:00
Igor Minar 0c4997f7d8 style: name anonymous fn that causes initial digest for better debugging/profiling 2014-08-22 11:46:45 -07:00
Caitlin Potter d713ad1b66 fix(ngRepeat): allow aliasAs identifiers which contain but do not match reserved words
Currently if a reserved word occurs anywhere within the aliasAs identifier, we throw. This CL fixes
this behaviour by allowing these identifiers, since they are technically perfectly valid.

Closes #8729
2014-08-22 09:50:22 -04:00
Jeff Cross 066c049957 fix(input): use lowercase method to account for undefined type 2014-08-22 00:35:35 -07:00
danrbergman 9352bdfdaf docs(guide/module): update tag in description
the reference to 'myApp' module changed in the example from <html> to a <div>. Updating description
to reflect the new <div> tag.

Closes #8720
2014-08-21 23:33:21 -04:00
danrbergman b8b8411b15 docs(guide/module): make the use of ng-app explicit in example
Helpful for people new to Angular to see the ng-app declaration in context with the expression
example. This will help illustrate the "Important thing to notice" point which follows: "The
reference to myApp module in <html ng-app="myApp">. This is what bootstraps the app using your
module."

Closes #8673
2014-08-21 22:28:15 -04:00
Sekib Omazic 693e846add fix(Angular): make Date comparison in equals() NaN-aware
Make angular.equals() Date comparison NaN-aware to prevent infinite digest errors when a dealy watched
date has an invalid value.

Closes #8650
Closes #8715
2014-08-21 21:17:21 -04:00
Jeff Cross fdeaa74c6c chore(shrinkwrap): add angular-benchpress to shrinkwrap 2014-08-21 16:49:01 -07:00
Caitlin Potter 09de7b5db4 feat($compile): use allOrNothing interpolation for ngAttr*
allOrNothing interpolation is now used for ng-attr-*, under all circumstances. This prevents
uninitialized attributes from being added to the DOM with invalid values which cause errors
to be shown.

BREAKING CHANGE:

Now, ng-attr-* will never add the attribute to the DOM if any of the interpolated expressions
evaluate to `undefined`.

To work around this, initialize values which are intended to be the empty string with the
empty string:

For example, given the following markup:

    <div ng-attr-style="border-radius: {{value}}{{units}}"></div>

If $scope.value is `4`, and $scope.units is undefined, the resulting markup is unchanged:

    <div ng-attr-style="border-radius: {{value}}{{units}}"></div>

However, if $scope.units is `""`, then the resulting markup is updated:

    <div ng-attr-style="border-radius: {{value}}{{units}}" style="border-radius: 4"></div>

Closes #8376
Closes #8399
2014-08-21 19:31:50 -04:00
Caitlin Potter a7fb357fa1 fix(input): by default, do not trim input[type=password] values
Do not trim input[type=password] values

BREAKING CHANGE:

Previously, input[type=password] would trim values by default, and would require an explicit ng-trim="false"
to disable the trimming behaviour. After this CL, ng-trim no longer effects input[type=password], and will
never trim the password value.

Closes #8250
Closes #8230
2014-08-21 19:11:57 -04:00
Caitlin Potter 09b298705f fix(ngRepeat): make allowed aliasAs expressions more strict
Ensure that aliasAs expressions are valid simple identifiers. These are still assigned to $scope in the same way
that they were previously, however now you won't accidentally create a property named "filtered.collection".

This change additionally restricts identifiers to prevent the use of certain ECMAScript reserved words ("null",
"undefined", "this" --- should probably add "super", "try", "catch" and "finally" there too), as well as certain
properties used by $scope or ngRepeat, including $parent, $index, $even, $odd, $first, $middle, or $last.

Closes #8438
Closes #8440
2014-08-21 18:58:54 -04:00
Caitlin Potter b674003f41 chore(protractor): enable testing ng-app-included examples
/cc @petebacondarwin / @juliemr please review :>

Blocks #8673
Closes #8677
2014-08-21 18:54:44 -04:00
Caitlin Potter 787c5a76dc feat($compile): bind isolate scope properties to controller
It is now possible to ask the $compiler's isolate scope property machinery to bind isolate
scope properties to a controller rather than scope itself. This feature requires the use of
controllerAs, so that the controller-bound properties may still be referenced from binding
expressions in views.

The current syntax is to prefix the scope name with a '@', like so:

    scope: {
        "myData": "=someData",
        "myString": "@someInterpolation",
        "myExpr": "&someExpr"
    },
    controllerAs: "someCtrl",
    bindtoController: true

The putting of properties within the context of the controller will only occur if
controllerAs is used for an isolate scope with the `bindToController` property of the
directive definition object set to `true`.

Closes #7635
Closes #7645
2014-08-21 18:41:19 -04:00
Casey Flynn dfbe69c45a docs($interval): fix typo in example
It's not "nis", it's "is"! 〜( ̄▽ ̄)〜

Closes #8711
2014-08-21 15:29:02 -04:00
Lucas Galfaso 1339c11e36 refactor($q): make $q Promises A+ v1.1 compilant
The Promises A+ 1.1 spec introduces new constraints that would cause $q to fail,
particularly specs 2.3.1 and 2.3.3.

Newly satisfied requirements:

 * "then" functions that return the same fulfilled/rejected promise
	will fail with a TypeError
 * Support for edge cases where "then" is a value other than function

Full 1.1 spec: https://github.com/promises-aplus/promises-spec/tree/1.1.0

This commit also modifies the adapter to use "resolve" method instead of "fulfill"
2014-08-21 10:52:08 -07:00
Caitlin Potter a603e202cc fix(copy): clear array destinations correctly for non-array sources
Closes #8610
Closes #8702
2014-08-20 21:49:54 -04:00
Jeff Cross 0872388a1b fix(minErr): encode btstrpd error input to strip angle brackets
The $sanitize service was returning an empty string to the error page
because the input was usually a single html tag (sometimes it could be
`document`). This fix replaces angle brackets with html entities.

Closes #8683
2014-08-20 17:26:50 -07:00
Caitlin Potter 36230194be fix(forEach): match behaviour of Array.prototype.forEach (ignore missing properties)
Array.prototype.forEach will not invoke the callback function if the properety is not present in the
object. Because of this, we have the illusion of not iterating over non-added properties in a sparse
array.

From ECMAScript:

9. Repeat while k < len
     a. Let Pk be ToString(k).
     b. Let kPresent be HasProperty(O, Pk).
     c. ReturnIfAbrupt(kPresent).
     d. If kPresent is true, then
            i. Let kValue be Get(O, Pk)
            ... (steps for invoking the function and aborting if it throws)

Closes #8510
Closes #8522
Closes #8525
2014-08-20 19:27:49 -04:00
Henrik Nyh 14b3db369e docs(ngDisabled): clarify "don't do this" example
It's not clear until you read the whole thing that it's an explanation
of what *not* to do and why, so if you scan the page from the top, you
may use this bad solution.
2014-08-20 15:44:23 -07:00
Brian Ford a9d227120d fix(linky): handle quotes around email addresses
Closes #8520
2014-08-20 13:37:45 -07:00
mishoo78 05791c0133 docs(ngMock): note that inject/module helpers only defined for jasmine / mocha
Closes #8694
2014-08-20 13:43:14 -04:00
Ole Weitz 00d5fde49c docs($cacheFactory): prevent example breaking on key update
The example for $cacheFactory breaks when a user tries to update a value for a key.
Setting a new value for an existing key results in duplicate key entries in the key array, thus
breaking the ng-repeat directive. With this fix the key is only added if it isn't contained in the
cache.

Closes #8214
2014-08-20 10:48:29 -04:00
Izhaki 39f6e229c2 docs($compile): fix documentation for ?^ controller search
Fixed typo: 'parents parents' to 'parents'

Closes #8690
2014-08-20 09:31:17 -04:00
Igor Minar 8863b9d04c perf($parse): don't bind filters to a context
This change gives us ~10% boost in Chrome, less or nothing in other browsers.

BREAKING CHANGE:  `this` in filters is now undefined and no longer the scope

It's a bad practice for filters to have hidden dependencies, so pulling stuff from scope directly
is not a good idea. Scope being the filter context was never documented as public api, so we don't
expect that any significant code depends on this behavior.

If an existing filter has a dependency on the scope instance, the scope reference can
be passed into the filter as a filter argument (this is highly discouraged for new code):

Before: `{{ user.name | customFilter }}`
After: `{{ user.name | customFilter:this }}`
2014-08-19 20:56:57 -07:00
Caitlin Potter d18b281976 fix($location): rewrite relative URI correctly if path==='/' in legacy html5Mode
Currently, legacy browsers get to use a clever scheme for resolving relative URIs in html5Mode,
and resolve the URI relative to $location.path().

Currently, $location.path() can be '/' under certain circumstances, which means that when we
split $location.path() on '/' and later join by '/' after adding another path component,
we end up with '//pathComponent'. $$rewrite fails to deal with this correctly, and effectively
the $location is never changed from the root path.

This CL corrects this by ensuring that the duplicate '/' situation does not occur when resolving
relative URIs.

Closes #8684
2014-08-19 21:31:02 -04:00
Jason Bedard f02f7d9c15 fix($compile): update the jQuery .context when an element is replaced by replace:true directive
.context is a deprecated jQuery api still being used by at least live() queries, so
we need to keep it in up to date during replacement.

Because of the if check, we can be sure that we replace the context only when jQuery is being
used and the context property is set to the element being replaced.

Closes #8253
Closes #7900
2014-08-19 17:24:34 -07:00
Lucas Galfaso 7eae29e5ab perf($rootScope): do not use Function::call when not needed
When a `$watchGroup` delegates the call to a `$watch`, there is no
need to keep the context of `this`
2014-08-20 00:57:31 +01:00
Lucas Galfaso 94b5c9f00e perf($interpolate): do not keep empty separators
Do not keep empty separators and keep references to where
each expression goes
2014-08-20 00:57:31 +01:00
Caitlin Potter 5b77e30c1a fix($location): don't call indexOf() of undefined href attribute
Closes #7721
Closes #8681
2014-08-19 19:16:02 -04:00
Brian Ford b7e82a33ee fix($sanitize): sanitize javascript urls with comments
Closes #8274
2014-08-19 14:10:54 -07:00
Marty Kane 6fdaa3d5a6 docs(guide/di): correct a few awkward sentences
Closes #8678
2014-08-19 16:50:48 -04:00
Izhaki d250dd43a3 docs($compile): correct documentation for directive controller ^ notation
`^` searches the element and its parents, not exclusively the element's parents. This confuses
a lot of people :(

Closes #8622
2014-08-19 14:30:11 -04:00
Shahar Talmi b8e54ef572 docs(*): use @description instead of @returns for properties
Dgeni-packages was not actually rendering the `@returns` text.

Closes #8639
2014-08-19 14:24:48 -04:00
Igor Minar e3a2ecf0db revert: refactor($compile): automatically append end comment nodes to all element-transclusion templates
This reverts commit 0d608d041f.

The commits caused more breaking changes at Google than initially expected and since its
benefit is small, so it's not worth keeping.
2014-08-19 10:57:50 -07:00
Baptiste Fontaine 63249a0aaf docs(ngBind): irrelevant text removed from ngBindHtml’s example
The ngBindHtml’s example had a copied line from ngBindTemplate’s that’s irrelevant here.

Closes #8668
2014-08-19 12:38:31 -04:00
Igor Minar 28b54bbfbf test(jqLite): add test for #wrap() when mutliple elements are being wrapped 2014-08-18 21:50:54 -07:00
chrisrhoden 77d3e75446 fix(jqLite): clone wrapNode in jqlite/wrap
Change jqLite's implementation of wrap() to clone the wrapNode before
wrapping the target element in it.
Match jQuery's wrap() behavior and prevent accidentally attaching
target element to the DOM as a side effect.

Closes #3860
Closes #4194
2014-08-18 21:50:44 -07:00
Igor Minar 1bdca93d70 fix(jqLite): revert the #ready() optimization until jQuery does the same
The change unfortunatelly makes us incompatible with jQuery which always falls back to onLoad.

Not falling back to onLoad is a possible breaking change because if Angular was added to the document during DOMContentLoaded
document.readyState at this point is 'interactive' which we'd need to add to our check, but more importantly if more scripts
are added during DOMContentLoaded these won't be loaded before we bootstrap, which can cause angular modules not to be found
during bootstrap.

This load ordering issues is really just a cornercase that should be handled via manual bootstrap, but until jQuery has the same
behavior we shouldn't do something else.
2014-08-18 21:20:12 -07:00
Igor Minar bf1a57ad48 fix(Scope): don't clear the phase when an exception is thrown from asyncQueue or watch
If we clear it here, then any other watch or async task could start a new digest.
2014-08-18 21:20:12 -07:00
Igor Minar ece6ef479c perf($parse): optimize filter implementation
- generate less garbage
- optimize argument collection
- use call instead of apply for no arg case (2x boost)
2014-08-18 21:20:12 -07:00
Igor Minar f7fde04160 style($parse): small readability improvements 2014-08-18 21:20:12 -07:00
Igor Minar 472019fb32 chore($parse): name anonymous functions for better debugging 2014-08-18 21:20:11 -07:00
Igor Minar a17578ad3d perf($parse): speed up fn invocation for no args case 2014-08-18 21:20:11 -07:00
Igor Minar cc16340e88 refactor($parse): small readability improvements 2014-08-18 21:20:11 -07:00
Igor Minar fecfc5b09f perf($parse): speed up fn invocation by optimizing arg collection
8-15% improvement for depending on the number of args
2014-08-18 21:20:11 -07:00
Igor Minar 6f5fc557ad refactor(jqLite): simplify jqLiteAddNodes when multiple nodes are being added
This branch is not as hot as the single node branch and the slice that we need for old webkit/phantom makes for loop preferable.
2014-08-18 21:20:11 -07:00
Igor Minar 0d608d041f refactor($compile): automatically append end comment nodes to all element-transclusion templates
Previously we would do it manually in all of our structural directives.

BREAKING CHANGE: element-transcluded directives now have an extra comment automatically appended to their cloned DOM

This comment is usually needed to keep track the end boundary in the event child directives modify the root node(s).
If not used for this purpose it can be safely ignored.
2014-08-18 21:20:11 -07:00
Igor Minar b5714ce1df refactor(ngRepeat): simplify previousNode boundary calculation
the previousNode was almost always correct except when we added a new block in which case incorrectly
assigned the cloned collection to the variable instead of the end comment node.
2014-08-18 21:20:11 -07:00
Igor Minar 27d4a4f0ca chore(ngRepeat): improve inline comments 2014-08-18 21:20:10 -07:00
Igor Minar 5cec4612c4 chore(ngRepeat): fix typo in a comment 2014-08-18 21:20:10 -07:00
Igor Minar 08eb05583b perf(ngRepeat): simplify code and remove duplicate array.length access
minimal perf gain (~2ms)
2014-08-18 21:20:10 -07:00
Igor Minar 2ef25887ef perF($compile): don't create jq wrapper for linkNode needlesly
when compileNode and linkNode are the same, we can reuse the existing jqLite wrapper.
2014-08-18 21:20:10 -07:00
Igor Minar f8f7a1df34 perf(jqLite): simplify jqLiteDealoc
while querySelectorAll is much more expensive than getElementsByTagName on elements with
both many and few children, cloning the live node list returned by getElementsByTagName
makes it as expensive as querySelectorAll (we need to clone because we need the node list
not to change while we iterate over it).

the childNodes and childNodes.length check is as expensive as querySelectorAll on a node
without any children, so it only makes the whole lookup 2x as slow, so I'm removing it.
2014-08-18 21:20:10 -07:00
Igor Minar b5f7970be5 perf($compile): don't register $destroy callbacks on element-transcluded nodes
This is a major perf win in the large table benchmark (~100ms or 9).

This cleanup is needed only for regular transclusion because only then the DOM hierarchy doesn't match scope hierarchy
(transcluded scope is a child of the parent scope and not a child of the isolate scope)

We should consider refactoring this further for the case of regular transclusion
and consider using scope events instead.
2014-08-18 21:20:10 -07:00
Igor Minar d05f27e274 perf(jqLite): optimize event handler 2014-08-18 21:20:09 -07:00
Igor Minar b0571517c5 refactor(isArray): use Array.isArray exclusively
IE9 supports Array.isArray so we don't need a polyfill any more.
2014-08-18 21:20:09 -07:00
Pawel Kozlowski c093c43b1f docs(orderBy): clarify expression usage in a predicate
Closes #8592
2014-08-18 13:32:09 -07:00
Tom Kadwill e1c85d1f98 docs(tutorial/index): improve wording
Removed repetition of 'machine' and 'local machine'.
I think this change makes the sentence more concise
2014-08-18 13:23:09 -07:00
Ciro Nunes 5feb9ab0f8 docs($compile): change restrict's defaults to EA
restrict defaults are EA let's update the docs
2014-08-18 13:12:11 -07:00
Jeff Cross 22bece7311 test(benchmark): add jQuery no-op script to large table benchmark 2014-08-18 11:00:23 -07:00
Jeff Sheets 65ec0ab70a docs($http): correct link to "salt (cryptography)" wikipedia article
Closes #8654
2014-08-18 13:34:07 -04:00
Caitlin Potter 6133c63214 docs(misc/contribute): fix syntax highlighting of URLS
Closes #8168
Closes #8169
2014-08-17 21:13:30 -04:00
Caitlin Potter 187b1b8ef4 perf(jqLite): only take str.split() path when needed
bda673f8e7 changed code to only use `str.split()` when necessary,
but the result was that `str.split()` would always be taken unless ' ' was the first character
in the string, negating the effectiveness of the perf fix.

Closes #8648
2014-08-17 17:49:42 -04:00
Igor Minar b24e381427 style(shallowCopy): use common for loop style 2014-08-16 22:32:35 -07:00
Igor Minar e3f26b5a6b style(jqLite): use the common for loop code style 2014-08-16 22:29:00 -07:00
Igor Minar c1cb341c87 refactor($compile): simplify controllersBoundTransclude check
no measurable perf difference, but the code more simple and minifies better
2014-08-16 22:10:04 -07:00
Igor Minar 0605e612e1 chore(angular.suffix): fix typo 2014-08-16 22:09:56 -07:00
Igor Minar 645625cf34 perf($compile): refactor publicLinkFn to simplify the code and use 'for in' loop 2014-08-16 22:09:48 -07:00
Igor Minar e822e9061c perf(Scope): optimize $watchCollection when used for watching objects
Since we control the oldValue, we don't need to worry about proto-inhereted properties which means we can use
'for in' and skip hasOwnProperty checks.

http://jsperf.com/for-in-vs-object-keys2
2014-08-16 22:09:38 -07:00
Igor Minar 301463a2e2 perf(Scope): don't use forEach in
doesn't make any significant impact on our current benchmarks because we don't have benchmarks with
many scope events, but this is a straightforward change worth doing
2014-08-16 22:09:29 -07:00
Igor Minar 7d96ab0d13 perf(Scope): watchCollection optimization
tiny ~4ms improvement and code that minifies better
2014-08-16 22:09:21 -07:00
Igor Minar 0a738ce176 perf(ngBind): bypass jquery/jqlite when setting text 2014-08-16 22:08:59 -07:00
Igor Minar d208ba2544 perf(isObject): use strict comparison
this is a micro-optimization based on http://jsperf.com/isobject4

no significant improvement in macro-benchmarks, but since it makes the code better it makes
sense making this change.
2014-08-16 22:06:14 -07:00
Igor Minar de3f238764 chore(test): rename getBlockElements to getBlockNodes in .jshintrc for tests 2014-08-16 22:00:10 -07:00
Igor Minar d302ea0cfa perf($parse): use no-proto maps as caches and avoid hasOwnProperty checks 2014-08-16 21:59:38 -07:00
Igor Minar a09fa35641 perf(Scope): exit $broadcast early if nobody is listening for the given event 2014-08-16 21:52:10 -07:00
Igor Minar 36e35b2cb1 perf(ngRepeat): optimize marking of nodes that are being removed via an animation 2014-08-16 21:52:04 -07:00
Igor Minar 13d113c522 perf(ngRepeat): use no-proto objects for blockMaps 2014-08-16 21:51:56 -07:00
Igor Minar 215d9545dc style(ngRepeat): ws and indentation fixes 2014-08-16 21:51:49 -07:00
Igor Minar bdd853cb83 perf(ngRepeat): move work to compile fn
this has impact only on nested repeaters where the number of columns is significant
2014-08-16 21:51:40 -07:00
Igor Minar e58d65a520 perf(ngRepeat): move updateScope fn to factory and reuse it for all repeaters 2014-08-16 21:51:33 -07:00
Igor Minar fbd48845e0 perf(ngRepeat): clone boundary comment nodes
http://jsperf.com/clone-vs-createcomment

most of the improvement comes from not reconcatinating the strings
2014-08-16 21:51:27 -07:00
Igor Minar abb17cce8b perf(jqLite): optimize off()
'for in' is much faster than Object.keys() and since the events object is ours, we know
that we don't need to worry about prototypically inherited properties so we can skip
expensive hasOwnProperty check.

http://jsperf.com/for-in-vs-object-keys2
2014-08-16 21:51:17 -07:00
Igor Minar 3e0a2e1f33 perf($compile): clone the nodeList during linking only if necessary 2014-08-16 21:51:06 -07:00
Igor Minar 1e8698b33e perf(jqLite): refactor jqLiteExpandoStore to minimize access to expensive element.ng339 expando property 2014-08-16 21:50:27 -07:00
Igor Minar 503dcb0281 style(jqLite): rename onFn to jqLiteOn 2014-08-16 21:31:41 -07:00
Igor Minar bf2e238418 refactor(jqLite): clean up jqLiteRemoveData fn 2014-08-16 21:31:35 -07:00
Igor Minar 8b77161702 refactor(Scope): remove useless compileToFn helper fn 2014-08-16 21:31:20 -07:00
Igor Minar 50e16a67bb refactor(Scope): rename $$childScopeClass to ChildClass to simplify debugging/profiling 2014-08-16 21:31:17 -07:00
Igor Minar b9b1aa7797 refactor($parse): simplify addInterceptor fn 2014-08-16 21:30:49 -07:00
Igor Minar a1341223c0 perf($parse): trim expression only if string 2014-08-16 21:30:44 -07:00
Igor Minar 99d70af11c style($parse): rename variables in generated code so that code is more readable 2014-08-16 21:30:38 -07:00
Igor Minar 6acea1152f fix($parse): remove unused variable declaration in generated getters 2014-08-16 21:30:32 -07:00
Igor Minar 33ab57948c style(ngRepeat): fix indentation 2014-08-16 21:30:27 -07:00
Igor Minar 31ed0af74b perf($compile): delay object initialization in nodeLinkFn 2014-08-16 21:30:20 -07:00
Igor Minar 13112710e6 refactor: remove unused variables 2014-08-16 21:30:07 -07:00
Igor Minar 54fa16e45d perf: speed up shallowCopy and special case Attributes cloning
`for in` is much faster than `Object.keys()` but `for in` includes properties from the prototype.

http://jsperf.com/for-in-vs-object-keys2

All the uses of shallowCopy don't deal with objects with heavy prototypes, except for Attributes instances
in $compile.

For this reason it's better to special-case Attributes constructor and make it do it's own shallow copy.
This cleans up the Attribute/$compile code as well.
2014-08-16 21:29:51 -07:00
Igor Minar fb00210cb6 refactor(shallowCopy): microoptimization 2014-08-16 21:01:13 -07:00
Igor Minar fafbd49490 perf(jqLite): microoptimization in chaining fn
note: no siginificant difference observed in macrobenchmarks, so this is just to make
me feel better :)
2014-08-16 21:01:13 -07:00
Igor Minar bda673f8e7 perf(jqLite): don't use String#split in on() unless we need it 2014-08-16 21:01:13 -07:00
Igor Minar b678f314f1 refactor(jqLite): don't look up the entry needlessly 2014-08-16 21:01:13 -07:00
Igor Minar 550965f111 style(jqLite): remove MiskoCode(tm) 2014-08-16 21:01:13 -07:00
Igor Minar 443b521e22 perf(jqLite): don't check isString many times in constructor
Note: no significant perf gain in Chrome
2014-08-16 21:01:12 -07:00
Igor Minar e6a9f9e130 refactor: simplify trim fn now that IE9 has String#trim 2014-08-16 21:01:12 -07:00
Igor Minar 441ab5235c refactor: rename getBlockElements to more correct getBlockNodes 2014-08-16 21:01:11 -07:00
Igor Minar 6b7b40af74 style(ngBind): name anonymous link fn to ease debugging/profiling 2014-08-16 15:38:50 -07:00
Igor Minar edc586f911 refactor(ngBindHtml): improve readability of the code 2014-08-16 15:36:32 -07:00
Igor Minar c7393093ff refactor(ngRepeat): name anonymous transclude callback for better debugging 2014-08-16 15:32:43 -07:00
Igor Minar b493c62f6b perf(jqLite): optimize jqLiteAcceptsData method
This doesn't show up too high in profiles, but this code is cleaner anyway
2014-08-16 15:32:32 -07:00
Igor Minar 35134a0e23 perf($compile): optimize nodeLinkFn
Functions with try/catch block can't be optimized, so we can
move the try/catch block into a tiny fn and make it possible for the
complex nodeLinkFn to get optimized.
2014-08-16 15:32:24 -07:00
Igor Minar 8d933bf995 perf(jqLite): optimize append() and after() 2014-08-16 15:31:10 -07:00
Igor Minar 6251751ad7 perf(jqLite): don't register DOM listener for $destroy event
This even is fired purely within jqLite/jQuery so it doesn't make sense to register DOM listener here.

6% improvement in large table benchmark for both creation and destruction
2014-08-16 15:05:22 -07:00
Igor Minar 8f10dca300 refactor(jqLite): remove legacy code to support IE8 and older 2014-08-16 15:05:22 -07:00
Igor Minar 566f1015d2 perf(jqLite): optimize event listener registration 2014-08-16 14:31:29 -07:00
Igor Minar 274e9c4ddf perf($compile): optimize publicLinkFn 2014-08-16 14:31:29 -07:00
Igor Minar e9cd6dc055 perf(jqLite): improve createEventHandler method by switching from forEach to for loop 2014-08-16 14:31:29 -07:00
Igor Minar 960a841051 perf(jqLite): don't use forEach in #off
off() is called on each element removal, so we want to make it as fast as possible
2014-08-16 14:31:28 -07:00
Igor Minar 01b10d7a24 refactor(jqLite): remove code duplication 2014-08-16 14:31:28 -07:00
Igor Minar 2a5dbbdc52 refactor(jqLite): don't recreate mouse event map 2014-08-16 14:31:28 -07:00
Igor Minar 6c4d601ff6 refactor(jqLite): drop Node.contains polyfill
Node.contains is supported on IE5+ and all the other browsers we care about.
2014-08-16 14:31:24 -07:00
Igor Minar d1536e7c8b perf(jqLite): don't recreate the Node.contains polyfill 2014-08-16 14:22:56 -07:00
Ken Sheedlo a19131494c style($rootScope): add semicolon for jshint 2014-08-15 17:17:55 -07:00
Tobias Bosch a353ed834c refactor(perf): migration event delegation benchmark to benchpress 2014-08-15 16:03:59 -07:00
rodyhaddad bf0e83732a fix($watchGroup): call listener once when the watchExpressions array is empty 2014-08-15 15:53:51 -07:00
Igor Minar 0554c1aae4 chore(Scope): remove deregisterNotifier feature for $watch
We no longer have a need for this feature that was added to primarily support
$watchGroup (see previous commit).

BREAKING CHANGE: deregisterNotifier callback for $watch is no longer available

This api was available only in the last few 1.3 beta versions and is not
very useful for applications, so we don't expect that anyone will be affected
by this change.
2014-08-15 15:53:51 -07:00
Igor Minar 3f0e642eef perf(Scope): use remove the need for the extra watch in $watchGroup
Instead of using a counter and an extra watch, just schedule the reaction function via .

This gives us the same/similar ordering and coalecsing of updates as counter without the extra
overhead. Also the code is easier to read.

Since interpolation uses watchGroup, this change additionally improves performance of interpolation.

In large table benchmark digest cost went down by 15-20% for interpolation.

Closes #8396
2014-08-15 15:53:51 -07:00
J. Bruni 1a05daf5dc feat(jqLite): implement the detach method
Closes #5461
2014-08-14 21:19:44 +02:00
Michał Gołębiowski b9389b26ba fix(jQuery): cooperate with other libraries monkey-patching jQuery.cleanData
Some libraries (like jQuery UI) patch jQuery.cleanData as well. This commit
makes Angular work correctly even if such external patching was done after
the Angular one.

Fixes #8471
2014-08-14 21:09:13 +02:00
Jeff Cross 6bdaa4bc21 feat(benchpress): configure benchpress grunt task 2014-08-13 23:28:13 -07:00
Jeff Cross bfd311174d docs(benchpress): add readme with instructions on using benchpress 2014-08-13 23:28:13 -07:00
Jeff Cross 1229334fbd perf(benchpress): add benchpress node module and port over large table test 2014-08-13 23:28:13 -07:00
Jack Wearden 77a1acc7fc feat(ngRoute): add method for changing url params
Add a $route#updateParams method for changing the current route
parameters without having to build a URL and call $location#path.
Useful for apps with a structure involving programmatically moving
between pages on the current route, but with different :param
values.

Properties in the object passed to $route.updateParams() will be
added to the location as queryParams if not contained within the
route's path definition.
2014-08-13 14:11:58 -07:00
Namolovan Nicolae 56bd0378bf docs(guide/e2e-testing): correct link to protractor's getting started
angular/protractor@fcd973b#diff-f3b56000093113bd3bfb6c9c05e7e945 splits the overview doc into
multiple files, and removes overview.md from the repository entirely, making the current link a 404.

This CL points the link to the new getting-started document rather than the overview, and avoids
linking to a missing document.

Closes #8595
2014-08-13 13:20:27 -04:00
Peter Bacon Darwin 76e57a764f chore(doc-gen): move e2e tests into docs folder
These tests didn't really fit in the test folder as the docs app is mostly
a separate entity from the AngularJS codebase.
2014-08-13 11:24:19 +01:00
Caitlin Potter f30e2d093b docs(CHANGELOG.md): fix typo, it's 1.2.22 not 1.2.2!
Whoops!
2014-08-12 16:51:40 -04:00
Caitlin Potter b33716f42a docs(CHANGELOG.md): add changelog for v1.3.0-beta.18 and v1.2.22
Closes #8581
2014-08-12 13:16:32 -04:00
rodyhaddad 2d678f1d0a feat($parse): allow for assignments in ternary operator branches
Closes #8512
Closes #8484
CLoses #5434
2014-08-11 16:54:40 +01:00
Peter Bacon Darwin 01d81cdab3 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
2014-08-10 20:26:32 +01:00
Peter Bacon Darwin 37ba3b9493 test(docsAppE2E): check that param defaults are shown in docs
Closes https://github.com/angular/dgeni-packages/pull/58
2014-08-10 20:06:50 +01:00
Peter Bacon Darwin 33a815d557 test(docsAppE2E): tighten CSS selector to only find one element 2014-08-10 20:04:57 +01:00
Peter Bacon Darwin d09e3e923e chore(package.json): update to dgeni-packages 0.9.7 2014-08-10 17:42:06 +01:00
Caitlin Potter 5038bf79c6 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
2014-08-10 03:18:11 -04:00
Eddie Hedges e4e7e940f6 docs(guide): correct links to unit testing guides
Closes #8548
2014-08-09 14:00:11 -04:00
Jeff Cross a001a417d5 fix(Scope): add deregisterNotifier to oneTimeLiteralWatch signature
A reverted commit removed deregisterNotifier from the arguments that would be passed
to a watcherFn.
2014-08-08 18:11:38 -04:00
Jeff Cross b3047b9dc9 revert perf(Scope): remove the need for the extra watch in $watchGroup
This reverts commit 28540c804a.
2014-08-08 18:11:38 -04:00
Jeff Cross ce378f2582 revert chore(Scope): remove deregisterNotifier feature for $watch
This reverts commit d2f8f25af2.

Closes #8542
2014-08-08 18:11:30 -04:00
Derrick Mar 1b6a107a54 docs(tutorial/step-10): add mock image data to spec
Closes #8468
Closes #8535
2014-08-08 20:37:27 +01:00
Caitlin Potter 8c98d6a637 docs(http): don't use locale-specific uri for MDN link 2014-08-08 15:31:50 -04:00
Joey Yang acad09efa6 docs($http): fix broken markdown link in withCredentials description
Markdown typo in $http config documentation

Closes #7859
2014-08-08 15:29:26 -04:00
Juampy 07d528396e 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:03:31 -04:00
James Kleeh 7df7d1a9bc docs(guide/directive): explain how to require multiple controllers
Closes #8524
2014-08-07 15:12:49 +01:00
sixin210 fcd76d27e5 docs(guide/concepts): add min to numerical inputs
Closes #8495
2014-08-06 21:03:58 +01:00
cexbrayat a390612d15 docs(guide/controller): remove duplicate -Controller suffix
Closes #8482
2014-08-06 15:43:46 +01:00
paranoidandroid522 833e60a203 docs(ngHref): close the <a> tags in examples
Self closing <a> tags in the examples given make no sense because they won't
show up in the browser (and I think aren't even allowed according to HTML specs).
I've seen this confuse people over at stackoverflow.com who tried to copy/paste
those examples.

Closes #8488
2014-08-06 15:38:48 +01:00
Jeff H. Parrish 1bb4e87dd6 docs($resource): fix incorrect comment example for userId
Closes #8507
2014-08-06 15:11:54 +01:00
Matias Niemelä 60c13a17a7 chore: ignore .lvimrc files 2014-08-05 02:14:04 -04:00
Andrew Silluron 7085b2bcac docs($compile): fix typo 'default' spelling
Change spelling of 'defualt' to 'default'

Closes #8476
2014-08-04 18:47:59 -04:00
Caitlin Potter acf38b382b docs(CHANGELOG.md): add missing breaking change from 1.3.0-beta.14
Closes #8474
2014-08-04 17:28:18 -04:00
Andrew Barbarello 947532828e docs(ngController): global controller fns disabled by default
Update doc to reflect 3f2232b5a1,
which disabled use of global controller constructors (by default).

Closes #8466
2014-08-04 12:01:36 +01:00
Michał Gołębiowski 91d5640a2c docs($compile): event handlers are not copied from the replaced node 2014-08-04 12:42:52 +02:00
PatrickJS fc73256464 docs(form.js): fix ngdoc tags for $setSubmitted
See 108a69be17

Closes #8464
2014-08-04 11:37:16 +01:00
Jeff Cross 23bc92b17d perf($q): move Deferred and Promise methods to prototypes
NOTE: Deferred doesn't get all the advantages of moving methods to the prototype,
since the constructor binds instance methods to "this" to support unbounded execution.

Closes #8300
2014-08-03 22:53:09 -07:00
Joseph Spencer 48b34ddb79 docs($resource): clarify the meaning of @ in paramDefaults
Closes #8457
2014-08-03 17:14:53 +01:00
Shahar Talmi 477626d846 feat(ngMock): allow override of when/expect definitions
Closes #5766
Closes #8352
2014-08-03 17:08:48 +01:00
Peter Bacon Darwin 25a476ea09 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
2014-08-03 16:35:41 +01:00
Arturo Guzman dd2a803f4f perf(input): prevent additional $digest when input is already touched
@kevinjamesus86 noticed that the input control would trigger a $digest
cycle every time it was blurred, https://github.com/angular/angular.js/commit/adcc5a00bf582d2b291c18e99093bb0854f7217c#commitcomment-7129512.

After the control is in a $touched state, other $digest cycles are
unnecesary.

Closes #8450
2014-08-02 16:49:38 +01:00
rodyhaddad 7884c25643 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:11:53 -07:00
rodyhaddad c024f28217 fix($parse): one-time binding for literal expressions works as expected
Meaning the watcher is only removed when all the properties of the object, or
all the elements of the array, are defined.

Closes #8209
2014-08-01 18:03:16 -07:00
Nicolás Andrés Gallinal 108a69be17 feat(form): Add new $submitted state to forms
The $submitted state changes
- to true when the form is submitted
- to false when $setPristine is called on the form

A .ng-submitted class is added to the form when $submitted=true

Closes #8056
2014-08-01 16:54:07 -07:00
Tobias Bosch 52b77b6b89 chore(perf): add event delegation benchmark 2014-08-01 12:11:12 -07:00
cexbrayat e98258184a docs($compile): fix title level for multiElement
Closes #8444
2014-08-01 10:13:21 -04:00
Peter Bacon Darwin 0107bfcab6 docs(ngSubmit): add link to form docs to discourage double submission
Closes #6017
2014-07-31 21:26:43 +01:00
Michał Gołębiowski 9e7cb3c375 feat(jQuery): upgrade to jQuery to 2.1.1
The data jQuery method was re-implemented in 2.0 in a secure way. This made
current hacky Angular solution to move data between elements via changing the
value of the internal node[jQuery.expando] stop working. Instead, just copy the
data from the first element to the other one.

Testing cache leaks on jQuery 2.x is not possible in the same way as it's done
in jqLite or in jQuery 1.x as there is no publicly exposed data storage. One
way to test it would be to intercept all places where a jQuery object is created
to save a reference to the underlaying node but there is no single place in the
jQuery code through which all element creation passes (there are various
shortcuts for performance reasons). Instead we rely on jqLite.cache testing
to find potential data leaks.

BREAKING CHANGE: Angular no longer supports jQuery versions below 2.1.1.
2014-07-31 22:20:31 +02:00
Ken Sheedlo 38db2d4cec docs(error/$injector/unpr): inadvertently redefining a module can cause error
Closes #8421
2014-07-31 20:48:20 +01:00
Igor Minar 41cb588514 docs(faq): remove the mention of IE8 2014-07-31 11:32:12 -07:00
k-funk 1571950fe3 docs($http): add link to $http.path()
Closes #8424
2014-07-31 13:43:19 +01:00
Danielle 9836a2d696 docs(ngMockE2E): remove repeated word
Closes #8411
2014-07-31 13:40:33 +01:00
winsontam 97f230a983 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:30:52 -04:00
Peter Bacon Darwin 9a2f8e1778 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:04 +01:00
Igor Minar d2f8f25af2 chore(Scope): remove deregisterNotifier feature for $watch
We no longer have a need for this feature that was added to primarily support
$watchGroup (see previous commit).

BREAKING CHANGE: deregisterNotifier callback for $watch is no longer available

This api was available only in the last few 1.3 beta versions and is not
very useful for applications, so we don't expect that anyone will be affected
by this change.
2014-07-30 17:21:28 -07:00
Igor Minar 28540c804a perf(Scope): remove the need for the extra watch in $watchGroup
Instead of using a counter and an extra watch, just schedule the reaction function via $evalAsync.

This gives us the same/similar ordering and coalecsing of updates as counter without the extra
overhead. Also the code is easier to read.

Since interpolation uses watchGroup, this change additionally improves performance of interpolation.

In large table benchmark digest cost went down by 15-20% for interpolation.

Closes #8396
2014-07-30 17:20:58 -07:00
Dylan e329243df1 docs(input): fix small grammatical error
Closes #8422
2014-07-30 18:59:55 -04:00
Peter Bacon Darwin cdc7db3f35 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:13:23 +01:00
Peter Bacon Darwin 7fdd26e6f3 test(select): add extra expectations and comments for clarity 2014-07-30 23:08:26 +01:00
Erin Altenhof-Long 48568b49dc 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:08:26 +01:00
Erin Altenhof-Long f92f52e29d 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:08:26 +01:00
Erin Altenhof-Long 6e8bec6c83 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:08:26 +01:00
Erin Altenhof-Long c306d251f4 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:08:26 +01:00
rodyhaddad a00c9bca40 fix(jqLite): fix regression where mutating the dom tree on a event breaks jqLite.remove
Closes #8359
2014-07-30 11:13:36 -07:00
Caitlin Potter 34781f18cb 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:33:25 -04:00
Jeff Cross 3625803349 fix($location): add semicolon to whitelist of delimiters to unencode
Some servers require characters within path segments to contain semicolons,
such as `/;jsessionid=foo` in order to work correctly. RFC-3986 includes
semicolons as acceptable sub-delimiters inside of path and query, but $location
currently encodes semicolons. This can cause an infinite digest to occur since $location
is comparing the internal semicolon-encoded url with the semicolon-unencoded url returned
from window.location.href, causing Angular to believe the url is changing with each digest
loop.

This fix adds ";" to the list of characters to unencode after encoding queries or path segments.

Closes #5019
2014-07-29 11:03:21 -07:00
Misha Moroshko ca0f59e677 docs(dateFilter): fix milliseconds example
Closes #8389
2014-07-29 17:49:21 +01:00
Andrew Pham 38678cb65a docs(tutorial/step-2): warn reader not to minimise browser that Karma's running on
Closes #8386
2014-07-29 17:40:16 +01:00
Nathan Wiebe e5c6b7017b 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:40:59 -04:00
Shahar Talmi 3607c9822f feat(http): allow caching for JSONP requests
Closes #1947
Closes #8356
2014-07-29 09:40:18 +01:00
Sergio Sanguanini 90251138bd style(AngularPublic): add whitespace to jshint block
Closes #8360
2014-07-27 14:06:30 +01:00
rodyhaddad c03ad24903 fix($parse): correctly assign expressions who's path is undefined and that use brackets notation
Closes #8039
2014-07-26 23:24:34 -07:00
Andrew Farrell ccc3255fea docs(tutorial): explain how to modify the port or ip served by npm start
A developer working on a remote server will want to change the IP
address which npm start serves on. A developer working on a machine
which is already using port 8000 will want to change the port.

See https://github.com/angular/angular-phonecat/pull/191
2014-07-26 20:39:55 +01:00
Peter Bacon Darwin 583f37df5e docs(ngChange): clarify when the ngChange expression is evaluated
Closes  #7866
2014-07-26 10:59:14 +01:00
Bernhard Hofmann 4152155c25 docs(ngChange) might not evaluate due to ngPattern
When a pattern is defined for an input field, ngChange is not evaluated
if the input doesn't match the pattern. Only changes to or from matching
patterns evaluate the ngChange expression.

See #7866
2014-07-26 10:59:05 +01:00
Pawel Kozlowski 2e0a4e385c docs(Scope): clarify naming in the $watch example
Fixes #8254
Closes #8271
2014-07-26 08:41:34 +01:00
Julie Ralph 1f533ad485 chore(ci): pin sauce connect to v4.3 2014-07-25 14:51:47 -07:00
Ivan Alvarez 46f755a0bc 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:04 -07:00
Mitch Robb 0daaab0341 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:11:15 -07:00
Jeff Cross f684c21145 docs(changelog): release notes for 1.3.0-beta.17 and 1.2.21 2014-07-25 10:16:13 -07:00
Shahar Talmi 86340a59bf fix(angular.copy): clone regexp flags correctly
Closes #5781
Closes #8337
2014-07-25 16:37:53 +01:00
chirag c03b9e5ec4 style(Angular.js): remove unused variables
Closes #8331
2014-07-25 15:08:03 +01:00
dbwhddn10 683d722233 docs($rootScope): correct the $watch listener parameter description
Closes #8322
2014-07-25 14:47:12 +01:00
Peter Bacon Darwin fefb7eda40 docs(tutorial/step-2): note that ng-app now needs a module name
Closes #7655
2014-07-25 14:35:36 +01:00
TheMrSteve 37117ab53a docs(tutorial/step-3): note that the server needs to be running before running Protractor
Closes #7142
2014-07-25 13:30:17 +01:00
Igor Minar 11f5aeeee9 feat($compile): change directive's restrict setting to default to EA (element/attribute)
Previously we defaulted just to A because of IE8 which had a hard time with applying css styles to HTMLUnknownElements.

This is no longer the case with IE9, so we should make restrict default to EA. Doing so will make it easier to create
components and avoid matching errors when creating new directives

BREAKING CHANGE: directives now match elements by default unless specific restriction rules are set via `restrict` property.

This means that if a directive 'myFoo' previously didn't specify matching restrictrion, it will now match both the attribute
and element form.

Before:

 <div my-foo></div> <---- my-foo attribute matched the directive
 <my-foo></my-foo>  <---- no match

After:

 <div my-foo></div> <---- my-foo attribute matched the directive
 <my-foo></my-foo>  <---- my-foo element matched the directive

It is not expected that this will be a problem in practice because of widespread use of prefixes that make "<my-foo>" like
elements unlikely.

Closes #8321
2014-07-24 15:02:41 -07:00
Jeff Cross 925b2080a0 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:20:31 -07:00
Chris Chua 8a27abae89 fix(jqLite): triggerHandler support unbind self
Fixes .one if the event is invoked from triggerHandler.

Closes #5984
2014-07-24 13:47:28 -07:00
Caitlin Potter f3a763fd2e feat($q): add streamlined ES6-style interface for using $q
This potentially helps lead the way towards a more performant fly-weight implementation, as discussed
earlier in the year. Using a constructor means we can put things in the prototype chain, and essentially
treat $q as a Promise class, and reuse methods as appropriate.

Short of that, I feel this style is slightly more convenient and streamlined, compared with the older
API.

Closes #8311
Closes #6427 (I know it's not really the solution asked for in #6427, sorry!)
2014-07-24 16:42:28 -04:00
Igor Minar c54228fbe9 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:40:23 -07:00
Patrick Hallisey 99a2f0aba7 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:01:43 -07:00
Shahar Talmi 469ea3384a fix(ngHref): remove attribute when empty value instead of ignoring
Closes #2755
2014-07-23 12:37:47 -07:00
Diego Plentz 1a2ed705d4 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:30:13 -07:00
Karl Yang d0de0ce557 docs(tutorial): remove index.html from app url 2014-07-23 10:32:11 -07:00
Chad Smith 88765d581d 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:19:58 -07:00
Shahar Talmi d1df21e45e 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.
2014-07-22 16:31:24 -07:00
Julie Ralph 4d875faa22 chore(e2e): protractor version bump to 1.0 2014-07-22 12:04:51 -07:00
hanstest 289b6b4dac docs(guide/directive): fix formatting 2014-07-22 10:33:24 -07:00
dbwhddn10 c4c83ef756 docs($interpolate): fix example
Closes #8276
2014-07-22 10:31:15 -07:00
Peter Bacon Darwin 38ad144c33 docs(guide/$location): fix up example protractor tests
Closes #8255
2014-07-22 17:54:53 +01:00
vdyckn df58874747 docs(guide/$location) global cntl deprecated
Closes #8255
2014-07-22 17:54:53 +01:00
Matias Niemelä e0adb9c452 feat(ngRepeat): provide support for aliasing filtered repeater results as a scope member
ngRepeat can now alias the snapshot of the list of items evaluated after all filters have
been applied as a property on the scope. Prior to this fix, when a filter is applied on a
repeater, there is no way to trigger an event when the repeater renders zero results.

Closes #5919
Closes #8046
Closes #8282
2014-07-21 22:16:45 -04:00
Shane Keller eff00ea98c docs(guide/scope): add missing period 2014-07-21 17:16:45 -07:00
Jason Hamm 92a10d843e docs(guide/bootstrap): fix example 2014-07-21 16:53:07 -07:00
Vikram Soni dfd228497b 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:09:03 -07:00
Jesse Palmer 3b158aab22 docs(misc/faq): minor formatting fixes 2014-07-21 15:29:34 -07:00
garetht f309c4ceba 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:54:51 -07:00
Trey Hunner a54d4600b3 style: fix whitespace issues
Closes #8277
2014-07-21 14:52:41 -07:00
Nick Van Dyck b5f0721e3d 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:44:11 -07:00
Trey Hunner f6f469e909 chore(.editorconfig): add .editorconfig file
Closes #8278
2014-07-21 14:42:36 -07:00
Igor Minar 0209b2e3b2 style($http): fix indentation 2014-07-21 14:42:09 -07:00
Peter Bacon Darwin 2ad1b4cb9c docs(ngMock) add @packageName tag to fix invalid module overview pages
Closes #7284
Closes #8038
2014-07-21 21:02:22 +01:00
Peter Bacon Darwin 55c6ee39e3 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:02:22 +01:00
xi c94329a891 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:53:43 -07:00
rodyhaddad 3d0dcf68c1 chore(travis): get npm dependencies from npm-bundle-deps
npm-bundle-deps has been rewritten to be more robust
2014-07-18 15:34:30 -07:00
Peter Bacon Darwin aa7dbf0cf7 docs(indexPage): move latest versions to the top
Closes #7513
2014-07-18 21:49:43 +01:00
Brian Ford bd2fb3d9c0 docs(changelog): release notes for 1.3.0-beta.16 pizza-transubstantiation 2014-07-18 12:18:26 -07:00
Igor Minar 20f4f63786 style(ngBindHtml): semicolon\! 2014-07-18 11:38:07 -07:00
Igor Minar 903e7352c9 perf(ngBindHtml): move addClass to the compile phase
Closes #8261
2014-07-18 11:29:07 -07:00
Carlo s A. Guillen 3f4ee15139 fix($location): handle plus character in query strings
Closes #3042
2014-07-18 08:36:16 -07:00
Peter Bacon Darwin c20d438ac9 fix(ngSwitch): interoperate with multi-element transclude directives
Worked with @lgalfaso on the implementation here.

Closes #8235
Closes #8244
2014-07-18 11:24:54 +01:00
Peter Bacon Darwin 4f32e3eef1 fix(ngSwitch): use the correct transclusion scope
If an ngSwitchWhen or ngSwitchDefault directive is on an element that also
contains a transclusion directive (such as ngRepeat) the new scope should
be the one provided by the bound transclusion function.

Previously we were incorrectly creating a simple child of the main ngSwitch
scope.

BREAKING CHANGE:
** Directive Priority Changed ** - this commit changes the priority
of `ngSwitchWhen` and `ngSwitchDefault` from 800 to 1200.  This makes their
priority higher than `ngRepeat`, which allows items to be repeated on
the switch case element reliably.

In general your directives should have a lower priority than these directives
if you want them to exist inside the case elements. If you relied on the
priority of these directives then you should check that your code still
operates correctly.

Closes #8235
2014-07-18 11:18:18 +01:00
Peter Bacon Darwin 81d9193ed7 docs(guide/module): add protractor tests 2014-07-18 11:05:39 +01:00
Peter Bacon Darwin 9987a609d0 style(guide/module): use dot first style when chaining 2014-07-18 11:05:24 +01:00
Nick Van Dyck 222edd8031 docs(guide/module) fixed global controller in example
Global controllers have been disallowed in Angular 1.3

Closes #8248
2014-07-18 10:51:11 +01:00
Jeff Cross 3ba98186b8 docs(input[date]): add note about lacking browser support 2014-07-17 18:54:17 -07:00
Jason Bedard e4ba89436a 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:14:13 -07:00
Jason Bedard a160f76ffa perf($compile): only create jqLite object when necessary 2014-07-17 17:14:13 -07:00
Peter Bacon Darwin d18172625a test(ngList): add protractor test to example 2014-07-17 22:04:07 +01:00
Peter Bacon Darwin 8d18d20e31 feat(ngList): use ngTrim to manage whitespace handling when splitting
With the removal of regular expression support `ngList` no longer supported
splitting on newlines (and other pure whitespace splitters).

This change allows the application developer to specify whether whitespace
should be respected or trimmed by using the `ngTrim` attribute. This also
makes `ngList` consistent with the standard use of `ngTrim` in input directives
in general.

Related To: #4344
2014-07-17 22:04:07 +01:00
Steve Purcell c6c9d26e34 fix(ngList): use custom separators for re-joining list items
The separator string used to split the view value into a list for the model
value is now used to join the list items back together again for the view value.

BREAKING CHANGE:

The `ngList` directive no longer supports splitting the view value
via a regular expression. We need to be able to re-join list items back
together and doing this when you can split with regular expressions can
lead to inconsistent behaviour and would be much more complex to support.

If your application relies upon ngList splitting with a regular expression
then you should either try to convert the separator to a simple string or
you can implement your own version of this directive for you application.

Closes #4008
Closes #2561
Closes #4344
2014-07-17 22:04:07 +01:00
Brian Ford 7c3122007c docs(triaging): clarify severity and frequency labels 2014-07-17 12:31:56 -07:00
Peter Bacon Darwin eb2bab40cc chore(package): update to latest dgeni-packages
This fixes an issue with HTML encoding HTML entities in code blocks
2014-07-17 12:54:54 +01:00
Julie Ralph 2474173e18 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:09:22 -07:00
Josh Schreuder 8cefb0b628 docs($interval): fix missing square brackets in example
Closes #8228
2014-07-16 20:42:02 -04:00
Caitlin Potter d7b3aa9ae6 test(jqLite): make iframe contents() test less flaky
Closes #8157
2014-07-16 17:45:33 -04:00
Paul Harris 3c7f0f7a36 test(filter): fix typo in descriptions
Two descriptions contain typo's to the word predicate.

Closes #8004
2014-07-16 17:04:09 -04:00
Caitlin Potter f6681d41a4 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:53:44 -04:00
Izhaki d25975438a docs($compile): fix template and replace properties' docs
Closes #8062
2014-07-16 13:42:38 -07:00
Andrew Tarry 1c9ab40d28 fix($cookie): use decodeURIComponent instead of unescape for cookie reading
the self.cookies method in $browser was using escape and unescape to handle the cookie name and value. These methods are deprecated and cause problems with some special characters (€). The method has been changed to use the replacement encodeURIComponent and decodeURIComponent.

Closes #8125
2014-07-16 12:54:56 -07:00
Caitlin Potter d6876f2906 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.

(Added to master branch to keep tree in sync)
2014-07-16 14:09:03 -04:00
Caitlin Potter 1f23980590 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:33:32 -04:00
Almar d2f348b04c 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:16 -04:00
Max 4adc44a3d1 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:14:24 +01:00
Caitlin Potter e8066c4b4c feat($compile): explicitly request multi-element directive behaviour
Directives which expect to make use of the multi-element grouping feature introduced in
1.1.6 (https://github.com/angular/angular.js/commit/e46100f7) must now add the property multiElement
to their definition object, with a truthy value.

This enables the use of directive attributes ending with the words '-start' and '-end' for
single-element directives.

BREAKING CHANGE: Directives which previously depended on the implicit grouping between
directive-start and directive-end attributes must be refactored in order to see this same behaviour.

Before:

```
<div data-fancy-directive-start>{{start}}</div>
  <p>Grouped content</p>
<div data-fancy-directive-end>{{end}}</div>

.directive('fancyDirective', function() {
  return {
    link: angular.noop
  };
})
```

After:

```
<div data-fancy-directive-start>{{start}}</div>
  <p>Grouped content</p>
<div data-fancy-directive-end>{{end}}</div>

.directive('fancyDirective', function() {
  return {
    multiElement: true, // Explicitly mark as a multi-element directive.
    link: angular.noop
  };
})
```

Closes #5372
Closes #6574
Closes #5370
Closes #8044
Closes #7336
2014-07-16 00:20:42 -04:00
vaibhav kohli 048a5f14ec style($injector): added whitespace 2014-07-15 17:22:33 -07:00
Lucas Galfaso 666a3835d2 refactor(bootstrap): Remove support for old bootstrap mechnanisms
Remove support for bootstrap detection using:

* The element id
* The element class.

E.g.

```
<div id="ng-app">...</div>
<div class="ng-app: module">...</div>
```

Removes reference to how to bootstrap using IE7

BREAKING CHANGE:

If using any of the mechanisms specified above, then migrate by
specifying the attribute `ng-app` to the root element. E.g.

```
<div ng-app="module">...</div>
```

Closes #8147
2014-07-15 17:20:26 -07:00
Dan Barua 9dce42b3c2 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:12 -07:00
rodyhaddad 8881606cd9 chore(travis): get npm dependencies from npm-bundle-deps 2014-07-15 17:09:28 -07:00
rodyhaddad 7e6e0d6a39 test(ngOptions): ensure that one-time bindings works in ngOptions
Related #7700

Closes #8029
2014-07-15 13:57:23 -07:00
rodyhaddad 86d55c1ded perf(*): more performant interpolation and lazy one-time binding
BEAKING CHANGE:
Lazy-binding now happens on the scope watcher level.

What this means is that given `parseFn = $parse('::foo')`,
bind-once will only kick in when `parseFn` is being watched by a scope
(i.e. `scope.$watch(parseFn)`)

Bind-once will have no effect when directily invoking `parseFn` (i.e. `parseFn()`)
2014-07-15 13:29:38 -07:00
rodyhaddad bcf72cacb5 revert: feat(*): lazy one-time binding support
This reverts commit cee429f0aa.

See #7700 for a more performant approach for bind-once.
2014-07-15 13:28:17 -07:00
Christian 840e889e53 docs(orderBy filter): fix controller name in example
Closes #8133
Closes #8206
2014-07-15 17:50:01 +01:00
rodyhaddad d7f730228d 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:46:55 -07:00
Shahar Talmi db9f2570c1 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:44:12 -07:00
Peter Bacon Darwin 4f45bf1a41 style($route): convert tab indent to spaces 2014-07-15 14:00:48 +01:00
Sekib Omazic 92bceb5c5b fix(orderBy): correctly order by date values
Closes #6675
Closes #6746
2014-07-15 13:40:18 +01:00
Jason Miller 528f56a690 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:17:36 +01:00
Wladimir Coka 345ed5d1c7 refactor($parse): improve readability on conditional assignment
Use logical OR operator instead of if statement

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

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

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

Closes #5065
2014-07-15 12:45:23 +01:00
Peter Bacon Darwin 1453fb72ff docs(guide/unit-testing): add info on testing element transclude directives
Closes #4505
Closes #8197
2014-07-15 12:39:36 +01:00
Vojta Jina 6f776102b2 chore(travis): increase browserNoActivityTimeout
We’ve seen many failures recently because of Karma killing a browser
after browserNoActivityTimeout. It’s possible that this is not any issue
other than super slow network / proxy.

Will try higher timeout and observe for a while.
2014-07-14 17:40:20 -07:00
Vojta Jina 42d497d1da chore(travis): enable SL video recording 2014-07-14 17:40:20 -07:00
Vojta Jina db464d3bcc test(jqLite): increase timeout and add a label
This test has been flaky on Sauce+IE.
I think 2secs might be not enough for IE sometimes.
2014-07-14 17:25:02 -07:00
Igor Minar 0113f22574 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:18:39 -07:00
rodyhaddad 02c0ed27bc fix($rootScope): remove support for a watch action to be a string
BREAKING CHANGE:

Previously, it was possible for an action passed to $watch
to be a string, interpreted as an angular expresison. This is no longer supported.
The action now has to be a function.
Passing an action to $watch is still optional.

Before:

```js
$scope.$watch('state', ' name="" ');
```

After:

```js
$scope.$watch('state', function () {
  $scope.name = "";
});
```

Closes #8190
2014-07-14 11:49:23 -07:00
Igor Minar 3dafcba9c1 feat(ngTransclude): allow ngTransclude to be used as an element
Closes #8141
2014-07-14 10:41:30 -07:00
standup75 071cbdb272 docs(ngAnimate): ensure the CSS breakdown example uses a compound selector 2014-07-14 11:27:02 -04:00
Jesse Palmer a2c7cf9fb2 docs($http): remove invalid JSDOC tags for patch() method
The @methodOf tag was causing a warning on build. I removed the tag and changed the @name to match
the previous comment blocks.

Closes #8170
2014-07-13 00:03:17 -04:00
Igor Minar af20a8aac6 docs($parse:isecdom): add a section about return values and CoffeeScript
Closes #7973
2014-07-12 20:23:37 -07:00
Erin Altenhof-Long d15cea48c3 docs(CHANGELOG): add v1.3.0-beta.15 and v1.2.20 changes 2014-07-11 11:15:42 -07:00
Jesse Palmer 363fb4fc79 docs(ngInclude): remove @eventOf jsdocs tag
The @eventOf tag was causing a warning on build. I removed the tag and changed the @name to match
the previous comment blocks.

Closes #8140
2014-07-11 00:43:28 -04:00
rodyhaddad 5f6b378e39 chore($parse): remove simpleGetter optimizations as they're no longer valid
Closes #8101
2014-07-10 15:16:41 -07:00
Pete Bacon Darwin 20b0c2420b docs(guide/migrate): add breaking changes for 1.3
See #8072
2014-07-10 22:44:34 +01:00
perek 34dcc0f109 fix($http) - add ability to remove default headers
Fixes #5784
Closes #5785
2014-07-10 14:37:28 -07:00
Michał Gołębiowski 81cd836137 docs(guide): switch from ngmin to ng-annotate
ng-annotate is an independent alternative to ngmin that is non-invasive
and more performant. For the background around the switch, see the discussion
at:
https://github.com/btford/ngmin/issues/93

Closes #8117
2014-07-10 14:14:30 -07:00
Jason Bedard c61626f10d test(jqLite): adding and removing data from SVG elements 2014-07-10 11:29:56 -07:00
rodyhaddad 012ab1f874 fix(jqLite): correctly dealoc svg elements in IE
SVG elements in IE don't have a `.children` but only `.childNodes` so it broke.
We started using `.children` for perf in e35abc9d2f.

This also acts as a perf improvements, since
`getElementsByTagName` is faster than traversing the tree.

Related #8075
2014-07-10 11:19:24 -07:00
rodyhaddad 9c5b407fd1 fix(jqLite): remove exposed dealoc method
The method doesn't exist in jQuery,
and there's shouldn't be any need for it
2014-07-10 10:38:24 -07:00
Erin Altenhof-Long 38bdb40675 docs(e2e-testing): fix broken protractor docs link 2014-07-10 09:51:11 -07:00
Peter Bacon Darwin 2e84cf9274 docs(ngModel): further mods to $viewValue semantics
Closes #8110
2014-07-09 14:54:42 +01:00
Shahar Talmi ada9852af8 docs(ngModel): objects passed to $setViewValue should be copied
Closes #8095
2014-07-09 14:54:42 +01:00
Igor Minar c4c8fbddd0 chore(travis): disable our npm registry cache 2014-07-09 06:37:10 -07:00
Michał Gołębiowski 9630d716e1 chore(travis): disable npm spinner & enable HTTP logs
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:41:46 +02:00
fuqcool cf4f85f62b docs(error/$sce/insecurl): fix links to $sce and $sceDelegateProvider 2014-07-08 22:38:49 -07:00
Julie Ralph 93510eb51b chore(tests): fix warning about a non-unique element locator in e2e tests 2014-07-08 16:26:47 -07:00
Julie Ralph 88a325771b 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:04 -07:00
Lucas Galfaso b8ae73e17c fix(select): auto-select new option that is marked as selected
When adding a new <option> element, if the DOM of this option element
states that the element is marked as `selected`, then select the new
<option> element

Closes #6828
2014-07-09 00:44:59 +02:00
Michał Gołębiowski 36831eccd1 refactor(jshint): reduce duplication & test all JS files 2014-07-08 15:49:25 +02:00
Michał Gołębiowski 7d4f0d79bd chore(jshint): update grunt-contrib-jshint 2014-07-08 15:49:18 +02:00
Brian Ford 5963b5c69f docs(guide/$location): update note about getter/setters 2014-07-08 04:36:26 -07:00
Domenico Matteo 621f678b2d docs(guide/i18n): fix typo 2014-07-08 03:34:27 -07:00
Brian Ford b9fcf01731 feat(ngModel): bind to getters/setters
Closes #768
2014-07-08 02:54:08 -07:00
Brian Ford 3f2232b5a1 feat($controller): disable using global controller constructors
With the exception of simple demos, it is not helpful to use globals
for controller constructors. This adds a new method to `$controllerProvider`
to re-enable the old behavior, but disables this feature by default.

BREAKING CHANGE:
`$controller` will no longer look for controllers on `window`.
The old behavior of looking on `window` for controllers was originally intended
for use in examples, demos, and toy apps. We found that allowing global controller
functions encouraged poor practices, so we resolved to disable this behavior by
default.

To migrate, register your controllers with modules rather than exposing them
as globals:

Before:

```javascript
function MyController() {
  // ...
}
```

After:

```javascript
angular.module('myApp', []).controller('MyController', [function() {
  // ...
}]);
```

Although it's not recommended, you can re-enable the old behavior like this:

```javascript
angular.module('myModule').config(['$controllerProvider', function($controllerProvider) {
  // this option might be handy for migrating old apps, but please don't use it
  // in new ones!
  $controllerProvider.allowGlobals();
}]);
```
2014-07-08 02:00:21 -07:00
Brian Ford d5305d5652 docs(select): update example to use a module 2014-07-08 02:00:21 -07:00
Brian Ford f9d8819861 docs(guide/expression): update examples to use modules 2014-07-08 02:00:20 -07:00
Brian Ford a5f6a92c8c docs(linky): update example to use a module 2014-07-08 02:00:20 -07:00
Brian Ford 282ed94cf9 docs(angular.copy): update example to use a module 2014-07-08 02:00:20 -07:00
Brian Ford 7279452898 docs($sanitize): update example to use a module 2014-07-08 02:00:20 -07:00
Brian Ford 7adcbb06c2 docs(guide/scope): update examples to use modules 2014-07-08 02:00:20 -07:00
Brian Ford 470ad11b2a docs(guide/forms): update examples to use modules 2014-07-08 02:00:20 -07:00
Brian Ford 9caff0df97 docs($location): update example to use a module 2014-07-08 02:00:20 -07:00
Brian Ford c0360890c5 docs($cookies): update examples to use modules 2014-07-08 02:00:19 -07:00
Brian Ford dba8b7e958 docs($sce): update example to use array annotations 2014-07-08 02:00:19 -07:00
Brian Ford b3da9467af docs(orderBy): update examples to use modules 2014-07-08 02:00:19 -07:00
Brian Ford e89916cf0a docs(limitTo): update example to use a module 2014-07-08 02:00:19 -07:00
Brian Ford ba2f606143 docs(ngTransclude): update example to use a module 2014-07-08 02:00:19 -07:00
Brian Ford 95c2738244 docs($log): update example to use a module 2014-07-08 02:00:19 -07:00
Brian Ford e83c5ba68e docs(ngPluralize): update example to use a module 2014-07-08 02:00:19 -07:00
Brian Ford 474251928e docs(ngSwitch): update example to use a module 2014-07-08 02:00:19 -07:00
Brian Ford aecdd9d630 docs(ngInit): update example to use a module 2014-07-08 02:00:18 -07:00
Brian Ford 1534529f8c docs(ngModelOptions): update examples to use modules 2014-07-08 02:00:18 -07:00
Brian Ford 0a1042535e docs(ngValue): update example to use a module 2014-07-08 02:00:18 -07:00
Brian Ford 39c7c909fb docs(ngList): update example to use a module 2014-07-08 02:00:18 -07:00
Brian Ford d28a0bf49e docs(ngInclude): update example to use a module 2014-07-08 02:00:18 -07:00
Brian Ford d35f50ee11 docs($interval): update example to use a module 2014-07-08 02:00:18 -07:00
Brian Ford 74014f57ed docs(filters): update examples to use modules 2014-07-08 02:00:18 -07:00
Brian Ford 0cddc5c7b4 docs(ngController): update examples to use modules 2014-07-08 02:00:18 -07:00
Brian Ford f3567b257c docs($window): update example to use a module 2014-07-08 02:00:17 -07:00
Brian Ford 84dc989cf0 docs(ngSubmit): update example to use a module 2014-07-08 02:00:17 -07:00
Brian Ford 1bce5bb3bb docs(ngBind): update examples to use modules 2014-07-08 02:00:17 -07:00
Brian Ford 28310583a9 docs($http): update example to use a module 2014-07-08 02:00:17 -07:00
Brian Ford 7ccab812fd docs($document): update example to use a module 2014-07-08 02:00:17 -07:00
Brian Ford e293975b1a docs(ngChange): update example to use a module 2014-07-08 02:00:17 -07:00
Brian Ford 86889b3b3c docs(ngModel): update examples to use modules 2014-07-08 02:00:17 -07:00
Brian Ford b9faec0673 docs(formDirective): update example to use a module 2014-07-08 02:00:17 -07:00
Brian Ford e1f3c0cce8 docs($compile): update example to use a module 2014-07-08 02:00:16 -07:00
Brian Ford 59c090127f docs($anchorScroll): update example to use a module 2014-07-08 02:00:11 -07:00
Shahar Talmi a88c215f17 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:00 -04:00
Julie Ralph 9b3961ce09 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:07 -07:00
Kevin Brogan af6f943a22 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:48:42 -04:00
Bill Neubauer 0a51a05d4e docs(tutorial/step-9): link to list of filters rather than filterProvider
Closes #8082
2014-07-06 07:43:21 +01:00
Caitlin Potter cb42766a14 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 20:44:36 -04:00
Chris Kuehl 095848915b docs(error/$rootScope/inprog): fix $timeout typo
Closes #8071
2014-07-03 17:32:30 -04:00
Peter Bacon Darwin 920c369f3d test(input): simplified $apply syntax 2014-07-03 22:07:37 +01:00
Shahar Talmi f3cb274116 fix(ngModel): test & update correct model when running $validate
If `$validate` is invoked when the model is already invalid, `$validate`
should pass `$$invalidModelValue` to the validators, not `$modelValue`.

Moreover, if `$validate` is invoked and it is found that the invalid model
has become valid, this previously invalid model should be assigned to
`$modelValue`.

Lastly, if `$validate` is invoked and it is found that the model has
become invalid, the previously valid model should be assigned to
`$$invalidModelValue`.

Closes #7836
Closes #7837
2014-07-03 22:07:37 +01:00
Peter Bacon Darwin 1a9cb0a258 docs($httpProvider): revert removal of comments
Related to #7782
2014-07-03 13:29:03 +01:00
Cory Boyd 6775972461 docs($httpProvider): add missing documentation
Add documentation for $httpProvider default values

Closes #7782
2014-07-03 13:25:25 +01:00
Peter Bacon Darwin 1fcbb69f50 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:50:57 +01:00
Peter Bacon Darwin ae0de07a1b docs(tutorial/step-0): remove hyphen and clarify items
Closes #5953
2014-07-03 12:49:22 +01:00
Robert Kielty b7c315558d 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:22:32 +01:00
Peter Bacon Darwin c0e6527226 docs(guide/controller): tweak initial example 2014-07-03 12:13:12 +01:00
cranesandcaff be41adc99f 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:01:20 +01:00
Peter Bacon Darwin 7e77521a78 docs(guide/di): further clarification of what can be injected 2014-07-03 10:13:21 +01:00
Artiom Neganov f66d6541b7 docs(guide/di): clarify what "services" can be injected into .config() and .run()
Closes #8106
2014-07-03 10:12:56 +01:00
Mike Haas 543cf1803b docs($compile): fix minor typo
Closes #8048
2014-07-03 09:50:41 +01:00
Peter Bacon Darwin 2f34950176 docs($logProvider): debugEnabled is a method not a property
Closes #7824
2014-07-03 09:45:03 +01:00
Peter Bacon Darwin 39915836e0 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:07 +01:00
Julie Ralph 63e89524f0 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-02 15:44:12 -07:00
Caitlin Potter c90cefe161 feat(input): support constant expressions for ngTrueValue/ngFalseValue
ngTrueValue and ngFalseValue now support parsed expressions which the parser determines to be constant values.

BREAKING CHANGE:

Previously, these attributes would always be treated as strings. However, they are now parsed as
expressions, and will throw if an expression is non-constant.

To convert non-constant strings into constant expressions, simply wrap them in an extra pair of quotes, like so:

    <input type="checkbox" ng-model="..." ng-true-value="'truthyValue'">

Closes #8041
Closes #5346
Closes #1199
2014-07-02 18:07:37 -04:00
Caitlin Potter 81214498ab 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:16 -04:00
jpsimons 894c7da2f3 docs($location): update $location.search() jsdoc signature
Closes #8050
2014-07-02 13:54:12 -07:00
Matias Niemelä f07af61f05 fix($animate): ensure that parallel class-based animations are all eventually closed
When multiple classes are added/removed in parallel then $animate only closes off the
last animation when the fallback timer has expired. Now all animations are closed off.

Fixes #7766
2014-07-02 02:32:27 +03:00
Jason Bedard b0ca5195e8 perf($compile): no longer need nodeType filter when setting $scope data
Closes #7887
2014-07-01 15:55:34 -07:00
Shahar Talmi 85b77314ed feat(FormController): add $rollbackViewValue to rollback all controls
Currently it is possible to use `ngModelOptions` to pend model updates until form is submitted, but in case the user wants to reset the form back to its original values he must call `$rollbackViewValue` on each input control in the form. This commit adds a `$rollbackViewValue` on the form controller in order to make this operation easier, similarly to `$commitViewValue`.

Closes #7595
2014-07-01 15:52:49 -07:00
Ahmed Nuaman d2963ad265 docs(guide): fixes to ngShow/ngHide animations 2014-07-02 01:41:13 +03:00
Ayrat Aminev e18db78d77 fix($animate): remove the ng-animate className after canceling animation
Closes #7784
Closes #7801
Closes #7894
2014-07-02 01:28:22 +03:00
Matias Niemelä ca752790d9 feat($animate): allow directives to cancel animation events
Closes #7722
2014-07-02 01:03:06 +03:00
Matias Niemelä 8252b8be94 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-02 00:21:57 +03:00
Sekib Omazic 2c7d0857cc 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:40:46 -07:00
Carlo s A. Guillen b3b5015cb7 docs(CHANGELOG.md): add changes for 1.3.0-beta.14 and 1.2.19 2014-06-30 16:59:25 -07:00
Martin Staffa c7c363cf8d fix($http): don't remove content-type header if data is set by request transform
Fixes #7910
2014-06-30 16:06:12 -07:00
rodyhaddad 2e6144670d style(parseSpec): make jshint happy 2014-06-30 09:52:32 -07:00
rodyhaddad 77ada4c82d 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 09:25:24 -07:00
rodyhaddad db713a1c1b refactor($parse): move around previous security changes made to $parse 2014-06-30 09:25:23 -07:00
Jann Horn 6081f20769 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:25:23 -07:00
Jann Horn 48fa3aadd5 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:25:23 -07:00
Jann Horn 528be29d16 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:25:23 -07:00
Igor Minar 2df721965b chore(saucelabs): add verbose tunnel logging flag
This will log all requests going through the tunnel which is helpful when debugging flakes
2014-06-30 08:57:08 -07:00
Igor Minar 36625de0d3 perf(forEach): use native for loop instead of forEach for Arrays 2014-06-30 08:48:25 -07:00
Kristian Hellang 31ae3e7164 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:01 -07:00
Julien Sanchez b59b04f98a fix(Angular.copy): preserve prototype chain when copying objects
So far, angular.copy was copying all properties including those from
prototype chain and was losing the whole prototype chain (except for Date,
Regexp, and Array).

Deep copy should exclude properties from the prototype chain because it
is useless to do so. When modified, properties from prototype chain are
overwritten on the object itself and will be deeply copied then.

Moreover, preserving prototype chain allows instanceof operator to be
consistent between the source object and the copy.
Before this change,

    var Foo = function() {};
    var foo = new Foo();
    var fooCopy = angular.copy(foo);
    foo instanceof Foo; // => true
    fooCopy instanceof Foo; // => false

Now,

    foo instanceof Foo; // => true
    fooCopy instanceof Foo; // => true

The new behaviour is useful when using $http transformResponse. When
receiving JSON data, we could transform it and instantiate real object
"types" from it. The transformed response is always copied by Angular.
The old behaviour was losing the whole prototype chain and broke all
"types" from third-party libraries depending on instanceof.

Closes #5063
Closes #3767
Closes #4996

BREAKING CHANGE:

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`.
2014-06-30 10:41:43 +01:00
vaibhav kohli ffdde26981 style(Angular.js): remove extra whitespace 2014-06-29 09:42:14 -07:00
rodyhaddad 075ba901f6 docs($rootScope): fix incorrect param name in $watchGroup description
Closes #7834
2014-06-28 21:59:16 -07:00
Archer 384c24808f docs(guide/$location): fix a typo
Change "window.location.path" to "window.location.pathname".

Closes #8012
2014-06-28 20:04:05 -07:00
Elnur Abdurrakhimov a87ffe37bf docs(Getting Started): fix typo
Closes #8015
2014-06-28 19:41:32 -07:00
rodyhaddad bc595509dd test($interval): add tests making sure $interval uses the methods from $window 2014-06-28 17:32:32 -07:00
Praveen a4904c0f83 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:32:32 -07:00
ncuillery d3c191ea63 docs(input): fix a typo 2014-06-28 15:14:45 -07:00
Shahar Talmi 7e71acd178 feat(jqLite): support isDefaultPrevented for triggerHandler dummies
triggerHandler sends dummy events to an element, but although the event includes the preventDefault method, there is no way to see if it was called for the event. This is sometimes important when testing directives that use preventDefault

Closes #8008
2014-06-27 17:10:10 -07:00
Efthymis Sarbanis 0235420196 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:13 -07:00
Caitlin Potter 19b6b3433a fix($timeout/$interval): if invokeApply is false, do not use evalAsync
$evalAsync triggers a digest, and is unsuitable when it is expected that a digest should not occur.

BREAKING CHANGE

Previously, even if invokeApply was set to false, a $rootScope digest would occur during promise
resolution. This is no longer the case, as promises returned from $timeout and $interval will no
longer trigger $evalAsync (which in turn causes a $digest) if `invokeApply` is false.

Workarounds include manually triggering $scope.$apply(), or returning $q.defer().promise from a
promise callback, and resolving or rejecting it when appropriate.

    var interval = $interval(function() {
      if (someRequirementFulfilled) {
        $interval.cancel(interval);
        $scope.$apply();
      }
    }, 100, 0, false);

or:

    var interval = $interval(function (idx) {
      // make the magic happen
    }, 1000, 10, false);
    interval.then(function(idx) {
      var deferred = $q.defer();
      // do the asynchronous magic --- $evalAsync will cause a digest and cause
      // bindings to update.
      return deferred.promise;
    });

Closes #7999
Closes #7103
2014-06-27 12:11:11 -04:00
Ciro Nunes b28b5caab1 fix($http): add the PATCH shortcut back
The shortcut was dropped because it had a lot of unkowns about PATCH.
Since we already know that using PATCH is good
(http://www.mnot.net/blog/2012/09/05/patch), and only IE8 has issues with that,
let's add the shortcut back.

Closes #5894
2014-06-27 15:23:42 +02:00
Igor Minar 26c20b75c6 revert: chore($resource): refactor confusing case statement
This reverts commit d50829bcf7.

This commit introduces a regression that results in urls with
parameters being incorrectly generated. We need to investigate
further why this is happening, for now I'm just reverting.
2014-06-26 13:48:10 -07:00
Michał Gołębiowski bdfc9c02d0 fix(core): drop the toBoolean function
So far Angular have used the toBoolean function to decide if the parsed value
is truthy. The function made more values falsy than regular JavaScript would,
e.g. strings 'f' and 'no' were both treated as falsy. This creates suble bugs
when backend sends a non-empty string with one of these values and something
suddenly hides in the application

Thanks to lgalfaso for test ideas.

BREAKING CHANGE: 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
2014-06-26 20:52:04 +01:00
Domenic Denicola e970df8554 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:36:39 -07:00
rodyhaddad a1c19c457b chore(ngMock): replace misplaced comma with semicolon 2014-06-26 12:32:01 -07:00
Laurent Curau c4b654b03c docs(guide/unit-testing): correct spelling 2014-06-26 12:20:57 -07:00
Eddie Hedges 1054dce4a9 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:01 -07:00
m-tretyak 1296e7a72e docs(srcset): fix mistake in example 2014-06-26 12:07:33 -07:00
thorn0 85f8b65442 docs($location): hashPrefix, html5Mode are methods
Closes #7915
2014-06-25 14:49:00 -07:00
Lucas Galfaso d9763f1bd3 fix($parse): handle constants as one-time binding expressions
Handle constant expressions as one-time binding expressions.
Avoids the infinite digest from
https://github.com/angular/angular.js/pull/7960/files#r14136938

Closes #7970
2014-06-25 22:38:18 +01:00
Peter Bacon Darwin 91754a76e0 fix(jqLite): never add to the cache for non-element/document nodes
Calling `jqLite.data()` on a disallowed node type caused an empty object to be added to the
cache. This could lead to memory leaks since we no longer clean up such node types when they are
removed from the DOM.

Closes #7966
2014-06-25 22:36:44 +01:00
Peter Bacon Darwin 768a1912cf test(compile): check transclusion/scopes work with multi-element directives 2014-06-25 22:34:04 +01:00
Peter Bacon Darwin 462dbb2016 fix(jqLite): don't attach event handlers to comments or text nodes
We were attaching handlers to comment nodes when setting up bound transclusion
functions. But we don't clean up comments and text nodes when deallocating so
there was a memory leak.

Closes #7913
Closes #7942
2014-06-25 22:34:04 +01:00
Peter Bacon Darwin 7f63e811ac test($compile): check no memory leak with coexisting element transcludes
If an element contains two "element" transcludes then the initial clone
consists of only comment nodes.  The concern was that this meant that
the transclude scopes would not be cleaned up.

But it turns out that in the case that there are only comments then the
scope is never attached to anything so we don't need to worry about cleaning
it up.

Later if a concrete element is created as part of the transclude then these
elements will have destroy handlers.
2014-06-25 22:32:46 +01:00
Peter Bacon Darwin cb43711f8f test($compile): check for memory leaks in nested transclusion 2014-06-25 22:32:46 +01:00
Caitlin Potter 1f6a5a1a92 fix(input): improve html5 validation support
This CL improves mocking support for HTML5 validation, and ensures that it works correctly along
with debounced commission of view values.

Closes #7936
Closes #7937
2014-06-24 08:35:00 -04:00
Christophe Krebser deb008d638 test(input): test that input[email"] and ngRequired don't interfere w/ eachother
ngRequired added to an email field wasn't working properly. ng-invalid-required
stayed true unless a valid email was entered.

correct behaviour is that it turns to ng-valid-required at first entered key.

Closes #7849
2014-06-24 00:58:05 -07:00
Matias Niemelä 6737924210 feat(NgModel): port the email input type to use the validators pipeline 2014-06-24 00:46:30 -07:00
Matias Niemelä 3ee6573063 feat(NgModel): port the URL input type to use the validators pipeline 2014-06-24 00:46:30 -07:00
Igor Minar 189cd064fe fix(numberFilter): correctly round fractions despite floating-point arithmetics issues in JS
Closes #7870
Closes #7878
2014-06-23 23:49:56 -07:00
Igor Minar ceaea861eb fix(jqLite): convert NodeList to an Array to make PhantomJS 1.x happy
Closes #7851
2014-06-23 21:58:38 -07:00
Igor Minar b1a6baac2d 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:19:41 -07:00
Michał Gołębiowski 43ff573bc8 chore(travis): declare Node.js version as '0.10', not 0.10 (which is 0.1) 2014-06-24 00:19:17 +02:00
Michał Gołębiowski e8e0750277 fix(testabilityPatch): fix invocations of angular.mock.dump 2014-06-23 23:38:15 +02:00
Zacky Ma ea820b53e1 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:35:03 -07:00
ephigabay 05ec6cc5c9 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:23:52 -07:00
Chaker Nakhli 0885446b82 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:13:53 -07:00
Shahar Talmi b775e2bca1 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:22 -04:00
Peter Bacon Darwin e57ad6a109 docs($provide): it is a service not an object
Closes #7917
2014-06-20 17:00:59 +01:00
Yuri Sulyma dafb8a3cd1 fix(Angular): nodeName should always be lowercase
XHTML uses lowercase node names, while HTML often uses uppercase.  The
generally accepted convention is to always lowercase them.

Fixes #3987
2014-06-20 14:58:02 +01:00
Laurent Curau ebff4c1fd2 docs(ngMessages): correct a typo
Closes #7918
2014-06-20 14:57:24 +01:00
Alex Muntada 28e6500a59 docs(tutorial/step-4): fix e2e test
After a protractor update the test syntax had to be changed.

Closes #7919
2014-06-20 14:35:57 +01:00
Neil Giarratana 307e72efab 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:42:34 -04:00
Shahar Talmi 2f0a448873 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:43:16 -04:00
Jason Bedard 8b0258d878 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.

Closes #7739
2014-06-16 19:15:36 -04:00
Ahmad Moussawi 928c7ecf39 docs($sce): update the parseAs method name 2014-06-16 13:44:07 -07:00
Jesse Houchins d50829bcf7 chore($resource): refactor confusing case statement 2014-06-16 13:26:12 -07:00
rodyhaddad 6addac397d docs(CHANGELOG.md): fix changes for 1.3.0-beta.13 2014-06-16 10:47:09 -07:00
rodyhaddad 1e4f5ccd3c docs(CHANGELOG.md): add changes for 1.3.0-beta.13 2014-06-16 10:45:21 -07:00
James Harrison Fisher 68dcb35ff9 docs(ngMock): fix typo providers -> provides
Should be a verb, ☆.。.:・゜☆MERCI BEAUCOUP☆.。.:・゜☆

Closes #7852
2014-06-16 11:45:29 -04:00
Colin Casey d7bfda61bf 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:25:54 +01:00
rodyhaddad 20c3c9e25f 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-13 16:23:42 -07:00
rodyhaddad 993ac8a59b docs(CHANGELOG.md): add changes for 1.2.18 and 1.3.0-beta.12 2014-06-13 15:04:44 -07:00
275 changed files with 19433 additions and 6334 deletions
-4
View File
@@ -1,4 +0,0 @@
{
"directory": "bower_components",
"json": "bower.json"
}
+21
View File
@@ -0,0 +1,21 @@
# http://editorconfig.org
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
[src/ngLocale/**]
insert_final_newline = false
[dropdown-toggle.js]
trim_trailing_whitespace = false
insert_final_newline = false
[htmlparser.js]
insert_final_newline = false
+3 -2
View File
@@ -1,4 +1,5 @@
/build/
/benchpress-build/
.DS_Store
gen_docs.disable
test.disable
@@ -9,11 +10,11 @@ performance/temp*.html
*.swp
angular.js.tmproj
/node_modules/
/components/
/bower_components/
bower_components/
angular.xcodeproj
.idea
.agignore
.lvimrc
libpeerconnection.log
npm-debug.log
/tmp/
+2
View File
@@ -0,0 +1,2 @@
node_modules/**
lib/htmlparser/**
+5
View File
@@ -0,0 +1,5 @@
{
"extends": ".jshintrc-base",
"node": true,
"globals": {}
}
+19
View File
@@ -0,0 +1,19 @@
{
"bitwise": true,
"immed": true,
"newcap": true,
"noarg": true,
"noempty": true,
"nonew": true,
"trailing": true,
"maxlen": 200,
"boss": true,
"eqnull": true,
"expr": true,
"globalstrict": true,
"laxbreak": true,
"loopfunc": true,
"sub": true,
"undef": true,
"indent": 2
}
+8 -5
View File
@@ -1,6 +1,6 @@
language: node_js
node_js:
- 0.10
- '0.10'
branches:
except:
@@ -11,7 +11,6 @@ env:
- JOB=unit
- JOB=e2e TEST_TARGET=jqlite
- JOB=e2e TEST_TARGET=jquery
- JOB=e2e TEST_TARGET=doce2e
global:
- SAUCE_USERNAME=angular-ci
- SAUCE_ACCESS_KEY=9b988f434ff8-fbca-8aa4-4ae3-35442987
@@ -19,9 +18,13 @@ env:
- BROWSER_PROVIDER_READY_FILE=/tmp/sauce-connect-ready
install:
- npm config set registry http://23.251.144.68
# Run npm install twice, because it is flaky.
- npm install || npm install
# - npm config set registry http://23.251.144.68
# Disable the spinner, it looks bad on Travis
- npm config set spin false
# Log HTTP requests
- npm config set loglevel http
- time ./scripts/travis/npm-bundle-deps.sh
- time npm install
before_script:
- mkdir -p $LOGS_DIR
+1936
View File
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -120,7 +120,7 @@ Before you submit your pull request consider the following guidelines:
```
* In GitHub, send a pull request to `angular:master`.
* If we suggest changes then
* If we suggest changes then
* Make the required updates.
* Re-run the Angular test suite to ensure tests are still passing.
* Rebase your branch and force push to your GitHub repository (this will update your Pull Request):
@@ -238,7 +238,7 @@ reference GitHub issues that this commit **Closes**.
A detailed explanation can be found in this [document][commit-message-format].
## <a name="cla"></a> Signing the CLA
## <a name="cla"></a> Signing the CLA
Please sign our Contributor License Agreement (CLA) before sending pull requests. For any code
changes to be accepted, the CLA must be signed. It's a quick process, we promise!
+18 -3
View File
@@ -1,3 +1,5 @@
'use strict';
var files = require('./angularFiles').files;
var util = require('./lib/grunt/utils.js');
var versionInfo = require('./lib/versions/version-info');
@@ -8,6 +10,7 @@ module.exports = function(grunt) {
require('load-grunt-tasks')(grunt);
grunt.loadTasks('lib/grunt');
grunt.loadNpmTasks('angular-benchpress');
var NG_VERSION = versionInfo.currentVersion;
NG_VERSION.cdn = versionInfo.cdnVersion;
@@ -20,7 +23,12 @@ module.exports = function(grunt) {
//config
grunt.initConfig({
NG_VERSION: NG_VERSION,
bp_build: {
options: {
buildPath: 'build/benchmarks',
benchmarksPath: 'benchmarks'
}
},
parallel: {
travis: {
tasks: [
@@ -107,6 +115,9 @@ module.exports = function(grunt) {
options: {
jshintrc: true,
},
node: {
files: { src: ['*.js', 'lib/**/*.js'] },
},
tests: {
files: { src: 'test/**/*.js' },
},
@@ -156,7 +167,7 @@ module.exports = function(grunt) {
scenario: {
dest: 'build/angular-scenario.js',
src: [
'bower_components/jquery/jquery.js',
'bower_components/jquery/dist/jquery.js',
util.wrap([files['angularSrc'], files['angularScenario']], 'ngScenario/angular')
],
styles: {
@@ -260,7 +271,11 @@ module.exports = function(grunt) {
compress: {
build: {
options: {archive: 'build/' + dist +'.zip', mode: 'zip'},
src: ['**'], cwd: 'build', expand: true, dot: true, dest: dist + '/'
src: ['**'],
cwd: 'build',
expand: true,
dot: true,
dest: dist + '/'
}
},
+2 -2
View File
@@ -15,7 +15,7 @@ it makes development fun!
* Tutorial: http://docs.angularjs.org/tutorial
* API Docs: http://docs.angularjs.org/api
* Developer Guide: http://docs.angularjs.org/guide
* Contribution guidelines: http://docs.angularjs.org/misc/contribute
* Contribution guidelines: [CONTRIBUTING.md](https://github.com/angular/angular.js/blob/master/CONTRIBUTING.md)
* Dashboard: http://dashboard.angularjs.org
Building AngularJS
@@ -37,7 +37,7 @@ To execute end-to-end (e2e) tests, use:
grunt test:e2e
To learn more about the grunt tasks, run `grunt --help` and also read our
[contribution guidelines](http://docs.angularjs.org/misc/contribute).
[contribution guidelines](https://github.com/angular/angular.js/blob/master/CONTRIBUTING.md).
[![Analytics](https://ga-beacon.appspot.com/UA-8594346-11/angular.js/README.md?pixel)](https://github.com/igrigorik/ga-beacon)
+4 -4
View File
@@ -44,11 +44,11 @@ This process based on the idea of minimizing user pain
* Label `needs: breaking change` - if needed
* Label `needs: public api` - if the issue requires introduction of a new public API
1. Label `browser: *` - if the issue **only** affects a certain browser
1. Label `frequency: *` How often does this issue come up? How many developers does this affect?
1. Label `frequency: *` How often does this issue come up? How many developers does this affect? Chose just one of the following:
* low - obscure issue affecting a handful of developers
* moderate - impacts a common usage pattern
* high - impacts most or all Angular apps
1. Label `severity: *` - How bad is the issue?
1. Label `severity: *` - How bad is the issue? Chose just one of the following:
* security issue
* regression
* memory leak
@@ -61,9 +61,9 @@ This process based on the idea of minimizing user pain
1. Label `origin: google` for issues from Google
1. Assign a milestone:
* Backlog - triaged fixes and features, should be the default choice
* Backlog - triaged fixes and features, should be the default choice
* Current 1.x.y milestone (e.g. 1.3.0-beta-2) - regressions and urgent bugs only
1. Unassign yourself from the issue
+7 -3
View File
@@ -1,4 +1,6 @@
angularFiles = {
'use strict';
var angularFiles = {
'angularSrc': [
'src/minErr.js',
'src/Angular.js',
@@ -32,6 +34,8 @@ angularFiles = {
'src/ng/sanitizeUri.js',
'src/ng/sce.js',
'src/ng/sniffer.js',
'src/ng/templateRequest.js',
'src/ng/testability.js',
'src/ng/timeout.js',
'src/ng/urlUtils.js',
'src/ng/window.js',
@@ -141,7 +145,7 @@ angularFiles = {
],
'karma': [
'bower_components/jquery/jquery.js',
'bower_components/jquery/dist/jquery.js',
'test/jquery_remove.js',
'@angularSrc',
'src/publishExternalApis.js',
@@ -175,7 +179,7 @@ angularFiles = {
],
'karmaJquery': [
'bower_components/jquery/jquery.js',
'bower_components/jquery/dist/jquery.js',
'test/jquery_alias.js',
'@angularSrc',
'src/publishExternalApis.js',
+6
View File
@@ -0,0 +1,6 @@
Instructions for using benchpress (how to create benchmarks, how to run, how to configure) can be
found at: https://github.com/angular/benchpress/blob/master/README.md.
In this project, there is a configured grunt task for building the benchmarks,
`grunt bp_build`, which places the runnable benchmarks in "/build/benchmarks/".
The existing `grunt webserver` task can be used to serve the built benchmarks at `localhost:8000/build/benchmarks/&lt;benchmark-name&gt;`
+57
View File
@@ -0,0 +1,57 @@
var app = angular.module('eventDelegationBenchmark', []);
app.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);
}
}
};
}]);
app.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...
}
};
});
app.controller('DataController', function($rootScope) {
this.ngRepeatCount = 1000;
this.rows = [];
var self = this;
benchmarkSteps.push({
name: '$apply',
fn: function() {
var oldRows = self.rows;
$rootScope.$apply(function() {
self.rows = [];
});
self.rows = oldRows;
if (self.rows.length !== self.ngRepeatCount) {
self.rows = [];
for (var i=0; i<self.ngRepeatCount; i++) {
self.rows.push('row'+i);
}
}
$rootScope.$apply();
}
});
});
+10
View File
@@ -0,0 +1,10 @@
module.exports = function(config) {
config.set({
scripts: [{
id: 'angular',
src: '/build/angular.js'
},{
src: 'app.js',
}]
});
};
+139
View File
@@ -0,0 +1,139 @@
<div ng-app="eventDelegationBenchmark">
<div ng-controller="DataController as ctrl">
<div class="container-fluid">
<p>
Impact of event delegation.
</p>
<p>
<label>
Number of ngRepeats:
<input type="number" ng-model="ctrl.ngRepeatCount">
</label>
</p>
<p>
<div class="radio"><label><input type=radio ng-model="benchmarkType" value="ngClick">ngClick</label></div>
<div class="radio"><label><input type=radio ng-model="benchmarkType" value="ngClickNoJqLite">ngClick without jqLite</label></div>
<div class="radio"><label><input type=radio ng-model="benchmarkType" value="ngShow">baseline: ng-show</label></div>
<div class="radio"><label><input type=radio ng-model="benchmarkType" value="textInterpolation">baseline: text interpolation</label></div>
<div class="radio"><label><input type=radio ng-model="benchmarkType" value="dlgtClick">delegate event directive (only compile)</label></div>
<div class="radio"><label><input type=radio ng-model="benchmarkType" value="noopDir">baseline: noop directive (compile and link)</label></div>
<div class="radio"><label><input type=radio ng-model="benchmarkType" value="noop">baseline: no directive</label></div>
</p>
<p>
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>
</p>
<p>
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 50% 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>
</p>
Debug output:
<ng-switch on="benchmarkType">
<div ng-switch-when="ngClick">
<div>
<span ng-repeat="row in ctrl.rows">
<span ng-click="a()">1</span>
<span ng-click="a()">1</span>
<span ng-click="a()">1</span>
<span ng-click="a()">1</span>
</span>
</div>
</div>
<div ng-switch-when="ngClickNoJqLite">
<div>
<span ng-repeat="row in ctrl.rows">
<span native-click="a()">1</span>
<span native-click="a()">1</span>
<span native-click="a()">1</span>
<span native-click="a()">1</span>
<span native-click="a()">1</span>
</span>
</div>
</div>
<div ng-switch-when="ngShow">
<div>
<span ng-repeat="row in ctrl.rows">
<span ng-show="true">1</span>
<span ng-show="true">1</span>
<span ng-show="true">1</span>
<span ng-show="true">1</span>
<span ng-show="true">1</span>
</span>
</div>
</div>
<div ng-switch-when="textInterpolation">
<div>
<span ng-repeat="row in ctrl.rows">
<span>{{row}}</span>
<span>{{row}}</span>
<span>{{row}}</span>
<span>{{row}}</span>
<span>{{row}}</span>
</span>
</div>
</div>
<div ng-switch-when="dlgtClick">
<div>
<span ng-repeat="row in ctrl.rows">
<span dlgt-click="a()">1</span>
<span dlgt-click="a()">1</span>
<span dlgt-click="a()">1</span>
<span dlgt-click="a()">1</span>
<span dlgt-click="a()">1</span>
</span>
</div>
</div>
<div ng-switch-when="noopDir">
<div>
<span ng-repeat="row in ctrl.rows">
<span noop-dir>1</span>
<span noop-dir>1</span>
<span noop-dir>1</span>
<span noop-dir>1</span>
<span noop-dir>1</span>
</span>
</div>
</div>
<div ng-switch-when="noop">
<div>
<span ng-repeat="row in ctrl.rows">
<span>1</span>
<span>1</span>
<span>1</span>
<span>1</span>
<span>1</span>
</span>
</div>
</div>
</ng-switch>
</div>
</div>
</div>
+183
View File
@@ -0,0 +1,183 @@
var app = angular.module('largetableBenchmark', []);
app.config(function($compileProvider) {
if ($compileProvider.debugInfoEnabled) {
$compileProvider.debugInfoEnabled(false);
}
});
app.filter('noop', function() {
return function(input) {
return input;
};
});
app.controller('DataController', function($scope, $rootScope) {
var totalRows = 1000;
var totalColumns = 20;
var data = $scope.data = [];
$scope.digestDuration = '?';
$scope.numberOfBindings = totalRows*totalColumns*2 + totalRows + 1;
$scope.numberOfWatches = '?';
function iGetter() { return this.i; }
function jGetter() { return this.j; }
for (var i=0; i<totalRows; i++) {
data[i] = [];
for (var j=0; j<totalColumns; j++) {
data[i][j] = {
i: i, j: j,
iFn: iGetter,
jFn: jGetter
};
}
}
var previousType;
benchmarkSteps.push({
name: 'destroy',
fn: function() {
$scope.$apply(function() {
previousType = $scope.benchmarkType;
$scope.benchmarkType = 'none';
});
}
});
benchmarkSteps.push({
name: 'create',
fn: function() {
$scope.$apply(function() {
$scope.benchmarkType = previousType;
});
}
});
benchmarkSteps.push({
name: '$apply',
fn: function() {
$rootScope.$apply();
}
});
});
var fn = function() { return 'x'};
app.directive('baselineBindingTable', function() {
return {
restrict: 'E',
link: function ($scope, $element) {
var i, j, row, cell, comment;
var template = document.createElement('span');
template.setAttribute('ng-repeat', 'foo in foos');
template.classList.add('ng-scope');
template.appendChild(document.createElement('span'));
template.appendChild(document.createTextNode(':'));
template.appendChild(document.createElement('span'));
template.appendChild(document.createTextNode('|'));
for (i = 0; i < 1000; i++) {
row = document.createElement('div');
$element[0].appendChild(row);
for (j = 0; j < 20; j++) {
cell = template.cloneNode(true);
row.appendChild(cell);
cell.childNodes[0].textContent = i;
cell.childNodes[2].textContent = j;
cell.ng3992 = 'xxx';
comment = document.createComment('ngRepeat end: bar in foo');
row.appendChild(comment);
}
comment = document.createComment('ngRepeat end: foo in foos');
$element[0].appendChild(comment);
}
}
};
});
app.directive('baselineInterpolationTable', function() {
return {
restrict: 'E',
link: function ($scope, $element) {
var i, j, row, cell, comment;
var template = document.createElement('span');
template.setAttribute('ng-repeat', 'foo in foos');
template.classList.add('ng-scope');
for (i = 0; i < 1000; i++) {
row = document.createElement('div');
$element[0].appendChild(row);
for (j = 0; j < 20; j++) {
cell = template.cloneNode(true);
row.appendChild(cell);
cell.textContent = '' + i + ':' + j + '|';
cell.ng3992 = 'xxx';
comment = document.createComment('ngRepeat end: bar in foo');
row.appendChild(comment);
}
comment = document.createComment('ngRepeat end: foo in foos');
$element[0].appendChild(comment);
}
}
};
});
/*
the fastest
240/44
app.directive('baselineTable', function() {
return function($scope, $element) {
var i, j, row, cell;
for (i = 0; i < 1000; i++) {
row = document.createElement('div');
for (j = 0; j < 20; j++) {
cell = document.createElement('span');
cell.textContent = '' + i + ':' + j;
row.appendChild(cell);
}
$element[0].appendChild(row);
}
};
});
*/
/*
with comments and expando
232/90
app.directive('baselineTable', function() {
return function($scope, $element) {
var i, j, row, cell, comment;
for (i = 0; i < 1000; i++) {
row = document.createElement('div');
$element[0].appendChild(row);
for (j = 0; j < 20; j++) {
cell = document.createElement('span');
row.appendChild(cell);
cell.textContent = '' + i + ':' + j;
cell.ng3992 = 'xxx';
comment = document.createComment('ngRepeat end: bar in foo');
row.appendChild(comment);
}
comment = document.createComment('ngRepeat end: foo in foos');
$element[0].appendChild(comment);
}
};
});
*/
+15
View File
@@ -0,0 +1,15 @@
module.exports = function(config) {
config.set({
scripts: [{
id: 'jquery',
src: 'jquery-noop.js'
},
{
id: 'angular',
src: '/build/angular.js'
},
{
src: 'app.js',
}]
});
};
+1
View File
@@ -0,0 +1 @@
//Override me with ?jquery=/bower_components/jquery/dist/jquery.js
+65
View File
@@ -0,0 +1,65 @@
<style>
[ng-cloak] { display: none; }
</style>
<div ng-app="largetableBenchmark" ng-cloak>
<div ng-controller="DataController">
<div class="container-fluid">
<p>
Large table rendered with AngularJS
</p>
<div>none: <input type=radio ng-model="benchmarkType" value="none"></div>
<div>baseline binding: <input type=radio ng-model="benchmarkType" value="baselineBinding"></div>
<div>baseline interpolation: <input type=radio ng-model="benchmarkType" value="baselineInterpolation"></div>
<div>ngBind: <input type=radio ng-model="benchmarkType" value="ngBind"></div>
<div>interpolation: <input type=radio ng-model="benchmarkType" value="interpolation"></div>
<div>ngBind + fnInvocation: <input type=radio ng-model="benchmarkType" value="ngBindFn"></div>
<div>interpolation + fnInvocation: <input type=radio ng-model="benchmarkType" value="interpolationFn"></div>
<div>ngBind + filter: <input type=radio ng-model="benchmarkType" value="ngBindFilter"></div>
<div>ngBind + filter: <input type=radio ng-model="benchmarkType" value="interpolationFilter"></div>
<ng-switch on="benchmarkType">
<baseline-binding-table ng-switch-when="baselineBinding">
</baseline-binding-table>
<baseline-interpolation-table ng-switch-when="baselineInterpolation">
</baseline-interpolation-table>
<div ng-switch-when="ngBind">
<h2>baseline binding</h2>
<div ng-repeat="row in data">
<span ng-repeat="column in row"><span ng-bind="column.i"></span>:<span ng-bind="column.j"></span>|</span>
</div>
</div>
<div ng-switch-when="interpolation">
<h2>baseline interpolation</h2>
<div ng-repeat="row in data">
<span ng-repeat="column in row">{{column.i}}:{{column.j}}|</span>
</div>
</div>
<div ng-switch-when="ngBindFn">
<h2>bindings with functions</h2>
<div ng-repeat="row in data">
<span ng-repeat="column in row"><span ng-bind="column.iFn()"></span>:<span ng-bind="column.jFn()"></span>|</span>
</div>
</div>
<div ng-switch-when="interpolationFn">
<h2>interpolation with functions</h2>
<div ng-repeat="row in data">
<span ng-repeat="column in row">{{column.iFn()}}:{{column.jFn()}}|</span>
</div>
</div>
<div ng-switch-when="ngBindFilter">
<h2>bindings with filter</h2>
<div ng-repeat="row in data">
<span ng-repeat="column in row"><span ng-bind="column.i | noop"></span>:<span ng-bind="column.j | noop"></span>|</span>
</div>
</div>
<div ng-switch-when="interpolationFilter">
<h2>interpolation with filter</h2>
<div ng-repeat="row in data">
<span ng-repeat="column in row">{{column.i | noop}}:{{column.j | noop}}|</span>
</div>
</div>
</ng-switch>
</div>
</div>
</div>
+48
View File
@@ -0,0 +1,48 @@
var app = angular.module('orderByBenchmark', []);
app.controller('DataController', function($rootScope, $scope) {
this.ngRepeatCount = 5000;
this.rows = [];
var self = this;
$scope.benchmarkType = 'basic';
$scope.rawProperty = function(key) {
return function(item) {
return item[key];
};
};
// Returns a random integer between min (included) and max (excluded)
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min)) + min;
}
benchmarkSteps.push({
name: 'setup',
description: 'Set rows to empty array and apply, then push new rows to be applied in next step',
fn: function() {
var oldRows = self.rows;
$rootScope.$apply(function() {
self.rows = [];
});
self.rows = oldRows;
if (self.rows.length !== self.ngRepeatCount) {
self.rows = [];
for (var i = 0; i < self.ngRepeatCount; i++) {
self.rows.push({
'name': getRandomInt(i, (i + 40)),
'index': i
});
}
}
}
})
benchmarkSteps.push({
name: '$apply',
fn: function() {
$rootScope.$apply();
}
});
});
+14
View File
@@ -0,0 +1,14 @@
module.exports = function(config) {
config.set({
scripts: [
{
"id": "jquery",
"src": "jquery-noop.js"
},{
id: 'angular',
src: '/build/angular.js'
},{
src: 'app.js',
}]
});
};
+82
View File
@@ -0,0 +1,82 @@
<div class="container-fluid" ng-app="orderByBenchmark">
<div class="row" ng-controller="DataController as ctrl">
<div class="col-lg-8">
<p>Filters</p>
<p>
<label>Number of ngRepeats:</label>
<input type="number" ng-model="ctrl.ngRepeatCount">
</p>
<p>
<div class="radio">
<label>
<input type="radio" ng-model="benchmarkType" value="baseline">baseline
</label>
</div>
<pre><code>ng-repeat="row in ctrl.rows"</code></pre>
<br />
<div class="radio">
<label>
<input type="radio" ng-model="benchmarkType" value="orderBy">orderBy
</label>
</div>
<pre><code>ng-repeat="row in ctrl.rows | orderBy:'name'"</code></pre>
<br />
<div class="radio">
<label>
<input type="radio" ng-model="benchmarkType" value="orderByArray">orderBy array expression
</label>
</div>
<pre><code>ng-repeat="row in ctrl.rows | orderBy:['name', 'index']"</code></pre>
<br />
<div class="radio">
<label>
<input type="radio" ng-model="benchmarkType"
value="orderByFunction">orderBy function expression
</label>
</div>
<pre><code>ng-repeat="row in ctrl.rows | orderBy:rawProperty('name')"</code></pre>
<br />
<div class="radio">
<label>
<input type="radio" ng-model="benchmarkType"
value="orderByArrayFunction">orderBy array function expression
</label>
</div>
<pre><code>ng-repeat="row in ctrl.rows | orderBy:[rawProperty('name'), rawProperty('index')]"</code></pre>
</p>
Debug output:
<ng-switch on="benchmarkType">
<div ng-switch-when="baseline">
<span ng-repeat="row in ctrl.rows">
<span ng-bind="row.name"></span>,
</span>
</div>
<div ng-switch-when="orderBy">
<span ng-repeat="row in ctrl.rows | orderBy:'name'">
<span ng-bind="row.name"></span>,
</span>
</div>
<div ng-switch-when="orderByArray">
<span ng-repeat="row in ctrl.rows | orderBy:['name', 'index']">
<span ng-bind="row.name"></span>,
</span>
</div>
<div ng-switch-when="orderByFunction">
<span ng-repeat="row in ctrl.rows | orderBy:rawProperty('name')">
<span ng-bind="row.name"></span>,
</span>
</div>
<div ng-switch-when="orderByArrayFunction">
<span ng-repeat="row in ctrl.rows | orderBy:[rawProperty('name'), rawProperty('index')]">
<span ng-bind="row.name"></span>,
</span>
</div>
</ng-switch>
</div>
</div>
</div>
+86
View File
@@ -0,0 +1,86 @@
var app = angular.module('parsedExpressionBenchmark', []);
app.config(function($compileProvider) {
if ($compileProvider.debugInfoEnabled) {
$compileProvider.debugInfoEnabled(false);
}
});
app.filter('noop', function() {
return function(input) {
return input;
};
});
//Executes the specified expression as a watcher
app.directive('bmPeWatch', function() {
return {
restrict: 'A',
compile: function($element, $attrs) {
$element.text( $attrs.bmPeWatch );
return function($scope, $element, $attrs) {
$scope.$watch($attrs.bmPeWatch, function(val) {
$element.text(val);
});
};
}
};
});
//Executes the specified expression as a watcher
//Adds a simple wrapper method to allow use of $watch instead of $watchCollection
app.directive('bmPeWatchLiteral', function($parse) {
function retZero() {
return 0;
}
return {
restrict: 'A',
compile: function($element, $attrs) {
$element.text( $attrs.bmPeWatchLiteral );
return function($scope, $element, $attrs) {
$scope.$watch( $parse($attrs.bmPeWatchLiteral, retZero) );
};
}
};
});
app.controller('DataController', function($scope, $rootScope) {
var totalRows = 10000;
var data = $scope.data = [];
var star = '*';
$scope.func = function() { return star;};
for (var i=0; i<totalRows; i++) {
data.push({
index: i,
odd: i%2 === 0,
even: i%2 === 1,
str0: "foo-" + Math.random()*Date.now(),
str1: "bar-" + Math.random()*Date.now(),
str2: "baz-" + Math.random()*Date.now(),
num0: Math.random()*Date.now(),
num1: Math.random()*Date.now(),
num2: Math.random()*Date.now(),
date0: new Date(Math.random()*Date.now()),
date1: new Date(Math.random()*Date.now()),
date2: new Date(Math.random()*Date.now()),
func: function(){ return star; },
obj: data[i-1],
keys: data[i-1] && (data[i-1].keys || Object.keys(data[i-1]))
});
}
benchmarkSteps.push({
name: '$apply',
fn: function() {
for (var i=0; i<50; i++) {
$rootScope.$digest();
}
}
});
});
+11
View File
@@ -0,0 +1,11 @@
module.exports = function(config) {
config.set({
scripts: [ {
id: 'angular',
src: '/build/angular.js'
},
{
src: 'app.js',
}]
});
};
+193
View File
@@ -0,0 +1,193 @@
<div ng-app="parsedExpressionBenchmark" ng-cloak>
<div ng-controller="DataController">
<div class="container-fluid">
<p>
Tests the execution of $parse()ed expressions. Each test tries to isolate specific expression types. Expressions should (probably) not be constant so they get evaluated per digest.
</p>
<ul style="list-style:none">
<li>
<input type="radio" ng-model="expressionType" value="simplePath" id="simplePath">
<label for="simplePath">Simple Paths</label>
</li>
<li>
<input type="radio" ng-model="expressionType" value="complexPath" id="complexPath">
<label for="complexPath">Complex Paths</label>
</li>
<li>
<input type="radio" ng-model="expressionType" value="fieldAccess" id="fieldAccess">
<label for="fieldAccess">Field Accessors</label>
</li>
<li>
<input type="radio" ng-model="expressionType" value="fieldIndex" id="fieldIndex">
<label for="fieldIndex">Field Indexes</label>
</li>
<li>
<input type="radio" ng-model="expressionType" value="operators" id="operators">
<label for="operators">Binary/Unary operators</label>
</li>
<li>
<input type="radio" ng-model="expressionType" value="filters" id="filters">
<label for="filters">Filters</label>
</li>
<li>
<input type="radio" ng-model="expressionType" value="functionCalls" id="functionCalls">
<label for="functionCalls">Function calls</label>
</li>
<li>
<input type="radio" ng-model="expressionType" value="objectLiterals" id="objectLiterals">
<label for="objectLiterals">Object Literals</label>
</li>
<li>
<input type="radio" ng-model="expressionType" value="arrayLiterals" id="arrayLiterals">
<label for="arrayLiterals">Array Literals</label>
</li>
</ul>
<!--
NOTES:
- ensure each tested expression has at least one variable in it to avoid constant expressions
-->
<ul ng-switch="expressionType">
<li ng-switch-when="simplePath" ng-repeat="(rowIdx, row) in ::data">
<span bm-pe-watch="rowIdx"></span>
<span bm-pe-watch="row.index"></span>
<span bm-pe-watch="row.num0"></span>
<span bm-pe-watch="row.num1"></span>
<span bm-pe-watch="row.num2"></span>
<span bm-pe-watch="row.str0"></span>
<span bm-pe-watch="row.str1"></span>
<span bm-pe-watch="row.str2"></span>
<span bm-pe-watch="row.date0"></span>
<span bm-pe-watch="row.obj"></span>
<span bm-pe-watch="row.keys"></span>
</li>
<li ng-switch-when="complexPath" ng-repeat="(rowIdx, row) in ::data">
<span bm-pe-watch="row.index"></span>
<span bm-pe-watch="row.num0"></span>
<span bm-pe-watch="row.num1"></span>
<span bm-pe-watch="row.str0"></span>
<span bm-pe-watch="row.str1"></span>
<span bm-pe-watch="row.obj.index"></span>
<span bm-pe-watch="row.obj.index"></span>
<span bm-pe-watch="row.obj.index"></span>
<span bm-pe-watch="row.obj.obj.index"></span>
<span bm-pe-watch="row.obj.obj.index"></span>
<span bm-pe-watch="row.obj.obj.obj.index"></span>
<span bm-pe-watch="row.obj.obj.obj.index"></span>
</li>
<li ng-switch-when="fieldAccess" ng-repeat="(rowIdx, row) in ::data">
<span bm-pe-watch="data[rowIdx].index"></span>
<span bm-pe-watch="data[rowIdx].num0"></span>
<span bm-pe-watch="data[rowIdx].num1"></span>
<span bm-pe-watch="data[rowIdx].str0"></span>
<span bm-pe-watch="data[rowIdx].str1"></span>
<span bm-pe-watch="data[rowIdx].obj.index"></span>
<span bm-pe-watch="data[rowIdx].obj.index"></span>
<span bm-pe-watch="data[rowIdx].obj.index"></span>
<span bm-pe-watch="data[rowIdx].obj.obj.index"></span>
<span bm-pe-watch="data[rowIdx].obj.obj.index"></span>
<span bm-pe-watch="data[rowIdx].obj.obj.obj.index"></span>
<span bm-pe-watch="data[rowIdx].obj.obj.obj.index"></span>
</li>
<li ng-switch-when="fieldIndex" ng-repeat="(rowIdx, row) in ::data">
<span bm-pe-watch="data[rowIdx]"></span>
<span bm-pe-watch="row['str0']"></span>
<span bm-pe-watch="row['str1']"></span>
<span bm-pe-watch="data[row['index']]['index']"></span>
<span bm-pe-watch="data[rowIdx]['obj']"></span>
<span bm-pe-watch="data[rowIdx]['obj']['obj']"></span>
<span bm-pe-watch="row[row['keys'][0]]"></span>
<span bm-pe-watch="row[row['keys'][1]]"></span>
<span bm-pe-watch="row[row['keys'][2]]"></span>
<span bm-pe-watch="row[row['keys'][3]]"></span>
<span bm-pe-watch="row[row['keys'][4]]"></span>
<span bm-pe-watch="row[row['keys'][5]]"></span>
</li>
<li ng-switch-when="operators" ng-repeat="(rowIdx, row) in ::data">
<span bm-pe-watch="+rowIdx"></span>
<span bm-pe-watch="-rowIdx"></span>
<span bm-pe-watch="rowIdx + 1"></span>
<span bm-pe-watch="rowIdx - 1"></span>
<span bm-pe-watch="rowIdx * 2"></span>
<span bm-pe-watch="rowIdx + -1"></span>
<span bm-pe-watch="rowIdx - -1"></span>
<span bm-pe-watch="-rowIdx * 2 + 1"></span>
<span bm-pe-watch="rowIdx % 2"></span>
<span bm-pe-watch="rowIdx % 2 === 1"></span>
<span bm-pe-watch="rowIdx % 2 === 0"></span>
<span bm-pe-watch="rowIdx / 1"></span>
<span bm-pe-watch="-rowIdx * 2 * rowIdx + rowIdx / rowIdx + 1"></span>
</li>
<li ng-switch-when="filters" ng-repeat="(rowIdx, row) in ::data">
<span bm-pe-watch="rowIdx | noop"></span>
<span bm-pe-watch="rowIdx | noop"></span>
<span bm-pe-watch="rowIdx | noop"></span>
<span bm-pe-watch="rowIdx | noop:1"></span>
<span bm-pe-watch="rowIdx | noop:rowIdx"></span>
<span bm-pe-watch="rowIdx | noop:1:2:3:4:5"></span>
<span bm-pe-watch="rowIdx | noop:rowIdx:rowIdx:rowIdx"></span>
<span bm-pe-watch="rowIdx | noop | noop"></span>
<span bm-pe-watch="rowIdx | noop:1 | noop"></span>
<span bm-pe-watch="rowIdx | noop | noop:null:undefined:0"></span>
<span bm-pe-watch="rowIdx | noop | noop | noop"></span>
<span bm-pe-watch="rowIdx | noop:1 | noop:2 | noop:3"></span>
</li>
<li ng-switch-when="functionCalls" ng-repeat="(rowIdx, row) in ::data">
<span bm-pe-watch="func()"></span>
<span bm-pe-watch="func(1)"></span>
<span bm-pe-watch="func(1, 2)"></span>
<span bm-pe-watch="func(1, 2, 3)"></span>
<span bm-pe-watch="row.func()"></span>
<span bm-pe-watch="row.func(1)"></span>
<span bm-pe-watch="row.func(1, 2)"></span>
<span bm-pe-watch="row.func(1, 2, 3)"></span>
<span bm-pe-watch="func(func())"></span>
<span bm-pe-watch="func(func(), func())"></span>
<span bm-pe-watch="row.func(row.func())"></span>
<span bm-pe-watch="row.func(row.func(), row.func())"></span>
</li>
<li ng-switch-when="objectLiterals" ng-repeat="(rowIdx, row) in ::data">
<span bm-pe-watch-literal="{foo: rowIdx}"></span>
<span bm-pe-watch-literal="{foo: row, bar: rowIdx}"></span>
<span bm-pe-watch-literal="{0: row, 1: rowIdx, 2: 3}"></span>
<span bm-pe-watch-literal="{str: 'foo', num: rowIdx, b: true}"></span>
<span bm-pe-watch-literal="{a: {b: {c: {d: {e: {f: rowIdx}}}}}}"></span>
<span bm-pe-watch-literal="{a: rowIdx, b: 1, c: 2, d: 3, e: 4, f: 5, g: rowIdx, h: 6, i: 7, j: 8, k: rowIdx}"></span>
</li>
<li ng-switch-when="arrayLiterals" ng-repeat="(rowIdx, row) in ::data">
<span bm-pe-watch-literal="[rowIdx]"></span>
<span bm-pe-watch-literal="[rowIdx, 0]"></span>
<span bm-pe-watch-literal="[rowIdx, 0, 1]"></span>
<span bm-pe-watch-literal="[rowIdx, 0, 1, 2]"></span>
<span bm-pe-watch-literal="[rowIdx, 0, 1, 2, 3]"></span>
<span bm-pe-watch-literal="[[], [rowIdx], [], [], [3], [[[]]]]"></span>
<span bm-pe-watch-literal="[rowIdx, undefined, null, true, false]"></span>
<span bm-pe-watch-literal="[[][0], [0][0], [][rowIdx]]"></span>
<span bm-pe-watch-literal="[0, rowIdx]"></span>
<span bm-pe-watch-literal="[0, 1, rowIdx]"></span>
<span bm-pe-watch-literal="[0, 1, 2, rowIdx]"></span>
<span bm-pe-watch-literal="[0, 1, 2, 3, rowIdx]"></span>
</li>
</ul>
</div>
</div>
</div>
+3 -7
View File
@@ -1,12 +1,8 @@
{
"name": "AngularJS",
"devDependencies": {
"jquery": "1.10.2",
"lunr.js": "0.4.3",
"open-sans-fontface": "1.0.4",
"google-code-prettify": "1.0.1",
"closure-compiler": "https://closure-compiler.googlecode.com/files/compiler-20130603.zip",
"ng-closure-runner": "https://raw.github.com/angular/ng-closure-runner/v0.2.3/assets/ng-closure-runner.zip",
"bootstrap": "3.1.1"
"jquery": "2.1.1",
"closure-compiler": "https://dl.google.com/closure-compiler/compiler-20140814.zip",
"ng-closure-runner": "https://raw.github.com/angular/ng-closure-runner/v0.2.3/assets/ng-closure-runner.zip"
}
}
+4 -2
View File
@@ -3,6 +3,8 @@
// TODO(vojta): pre-commit hook for validating messages
// TODO(vojta): report errors, currently Q silence everything which really sucks
'use strict';
var child = require('child_process');
var fs = require('fs');
var util = require('util');
@@ -164,7 +166,7 @@ var writeChangelog = function(stream, commits, version) {
hash: commit.hash,
closes: []
});
};
}
});
stream.write(util.format(HEADER_TPL, version, version, currentDate()));
@@ -172,7 +174,7 @@ var writeChangelog = function(stream, commits, version) {
printSection(stream, 'Features', sections.feat);
printSection(stream, 'Performance Improvements', sections.perf);
printSection(stream, 'Breaking Changes', sections.breaks, false);
}
};
var getPreviousTag = function() {
+5 -1
View File
@@ -1,3 +1,7 @@
/* global describe: false, it: false, expect: false */
'use strict';
describe('changelog.js', function() {
var ch = require('./changelog');
@@ -13,7 +17,7 @@ describe('changelog.js', function() {
expect(msg.hash).toBe('9b1aff905b638aa274a5fc8f88662df446d374bd');
expect(msg.subject).toBe('broadcast $destroy event on scope destruction');
expect(msg.body).toBe('perf testing shows that in chrome this change adds 5-15% overhead\n' +
'when destroying 10k nested scopes where each scope has a $destroy listener\n')
'when destroying 10k nested scopes where each scope has a $destroy listener\n');
expect(msg.component).toBe('scope');
});
+4 -2
View File
@@ -1,5 +1,7 @@
#!/usr/bin/env node
'use strict';
var util = require('util');
var cp = require('child_process');
@@ -143,10 +145,10 @@ then(allInSeries(function (branch) {
line = line.split(' ');
var sha = line.shift();
var msg = line.join(' ');
return sha + (msg.toLowerCase().indexOf('fix') === -1 ? ' ' : ' * ') + msg;
return sha + ((/fix\([^\)]+\):/i.test(msg)) ? ' * ' : ' ') + msg;
});
branch.log = log.map(function (line) {
return line.substr(41)
return line.substr(41);
});
return branch;
});
+10 -4
View File
@@ -211,6 +211,10 @@ code.highlighted {
color:maroon;
}
ul + p {
margin-top: 10px;
}
.docs-version-jump {
min-width:100%;
max-width:100%;
@@ -631,12 +635,14 @@ ul.events > li {
display:inline-block;
padding:3px 0;
}
.nav-index-group .nav-index-listing:not(.nav-index-section) + .nav-index-listing:not(.nav-index-section):after {
padding-right:5px;
content:", ";
.nav-index-group .nav-index-listing:not(.nav-index-section):after {
padding-right:5px;
margin-left:-3px;
content:", ";
}
.nav-index-group .nav-index-listing:last-child {
.nav-index-group .nav-index-listing:last-child:after {
content:"";
display:inline-block;
}
.nav-index-group .nav-index-section {
display:block;
+4
View File
@@ -6,6 +6,10 @@
line-height: 1.5;
}
.lang-text * {
color: #333333!important;
}
.pln {
color: #333333;
}
+1 -1
View File
@@ -40,7 +40,7 @@ pre.prettyprint.linenums {
}
ol.linenums {
margin: 0 0 0 33px; /* IE indents via margin-left */
}
}
ol.linenums li {
padding-left: 12px;
font-size:12px;
+3 -3
View File
@@ -11,7 +11,7 @@ directive.runnableExample = ['$templateCache', '$document', function($templateCa
'ng-repeat="tab in tabs track by $index" ' +
'href="" ' +
'class="btn"' +
'ng-click="setTab($index)">' +
'ng-click="setTab($index)">' +
' {{ tab }}' +
' </a>' +
'</nav>';
@@ -103,7 +103,7 @@ directive.syntax = function() {
restrict: 'A',
link: function(scope, element, attrs) {
function makeLink(type, text, link, icon) {
return '<a href="' + link + '" class="btn syntax-' + type + '" target="_blank" rel="nofollow">' +
return '<a href="' + link + '" class="btn syntax-' + type + '" target="_blank" rel="nofollow">' +
'<span class="' + icon + '"></span> ' + text +
'</a>';
};
@@ -307,7 +307,7 @@ var popoverElement = function() {
return this.titleElement.html(value);
},
content : function(value) {
content : function(value) {
if(value && value.length > 0) {
value = marked(value);
}
@@ -1,12 +1,35 @@
'use strict';
var webdriver = require('protractor/node_modules/selenium-webdriver');
describe('docs.angularjs.org', function () {
beforeEach(function() {
// read and clear logs from previous tests
browser.manage().logs().get('browser');
});
afterEach(function() {
// verify that there were no console errors in the browser
browser.manage().logs().get('browser').then(function(browserLog) {
var filteredLog = browserLog.filter(function(logEntry) {
return logEntry.level.value > webdriver.logging.Level.WARNING.value;
});
expect(filteredLog.length).toEqual(0);
if (filteredLog.length) {
console.log('browser console errors: ' + require('util').inspect(filteredLog));
}
});
});
describe('App', function () {
// it('should filter the module list when searching', function () {
// browser.get();
// browser.waitForAngular();
// var search = element(by.input('q'));
// var search = element(by.model('q'));
// search.clear();
// search.sendKeys('ngBind');
@@ -34,10 +57,10 @@ describe('docs.angularjs.org', function () {
browser.switchTo().frame('example-input-directive');
var nameInput = element(by.input('user.name'));
var nameInput = element(by.model('user.name'));
nameInput.sendKeys('!!!');
var code = element(by.css('tt'));
var code = element.all(by.css('tt')).first();
expect(code.getText()).toContain('guest!!!');
});
@@ -67,5 +90,28 @@ describe('docs.angularjs.org', function () {
browser.get('index-debug.html#!error/ng/areq?p0=Missing&p1=not%20a%20function,%20got%20undefined');
expect(element(by.css('.minerr-errmsg')).getText()).toEqual("Argument 'Missing' is not a function, got undefined");
});
it("should display links to code on GitHub", function() {
browser.get('index-debug.html#!/api/does/not/exist');
expect(element(by.css('h1')).getText()).toBe('Oops!');
});
});
describe("templates", function() {
it("should show parameter defaults", function() {
browser.get('index-debug.html#!/api/ng/service/$timeout');
expect(element.all(by.css('.input-arguments p em')).first().getText()).toContain('(default: 0)');
});
});
describe("API pages", function() {
it("should display links to code on GitHub", function() {
browser.get('index-debug.html#!/api/ng/service/$http');
expect(element(by.css('.improve-docs')).getAttribute('href')).toMatch(/https?:\/\/github\.com\/angular\/angular\.js\/edit\/.+\/src\/ng\/http\.js/);
browser.get('index-debug.html#!/api/ng/service/$http');
expect(element(by.css('.view-source')).getAttribute('href')).toMatch(/https?:\/\/github\.com\/angular\/angular\.js\/tree\/.+\/src\/ng\/http\.js#L\d+/);
});
});
});
+1 -1
View File
@@ -20,4 +20,4 @@ angular.module('docsApp', [
.config(function($locationProvider) {
$locationProvider.html5Mode(true).hashPrefix('!');
});
});
+1 -1
View File
@@ -33,7 +33,7 @@ angular.module('DocsController', [])
$scope.navClass = function(navItem) {
return {
active: navItem.href && this.currentPage.path,
active: navItem.href && this.currentPage && this.currentPage.path,
'nav-index-section': navItem.type === 'section'
};
};
+1 -1
View File
@@ -59,4 +59,4 @@ angular.module('errors', ['ngSanitize'])
element.html(errorLinkFilter(interpolate.apply(null, formatArgs), '_blank'));
}
};
}]);
}]);
+7 -2
View File
@@ -2,7 +2,12 @@ angular.module('examples', [])
.factory('formPostData', ['$document', function($document) {
return function(url, fields) {
var form = angular.element('<form style="display: none;" method="post" action="' + url + '" target="_blank"></form>');
/**
* 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.
*/
var form = angular.element('<form style="display: none;" method="post" action="' + url + '"></form>');
angular.forEach(fields, function(value, name) {
var input = angular.element('<input type="hidden" name="' + name + '">');
input.attr('value', value);
@@ -69,4 +74,4 @@ angular.module('examples', [])
formPostData('http://plnkr.co/edit/?p=preview', postData);
});
};
}]);
}]);
+1 -1
View File
@@ -21,4 +21,4 @@ angular.module('docsApp.navigationService', [])
}
};
});
});
+3 -1
View File
@@ -74,6 +74,7 @@ angular.module('search', [])
var index = lunrSearch(function() {
this.ref('id');
this.field('title', {boost: 50});
this.field('members', { boost: 40});
this.field('keywords', { boost : 20 });
});
@@ -82,7 +83,8 @@ angular.module('search', [])
index.store({
id : key,
title : page.searchTerms.titleWords,
keywords : page.searchTerms.keywords
keywords : page.searchTerms.keywords,
members : page.searchTerms.members
});
};
});
+19 -3
View File
@@ -1,15 +1,31 @@
"use strict";
angular.module('versions', [])
.controller('DocsVersionsCtrl', ['$scope', '$location', '$window', 'NG_VERSIONS', function($scope, $location, $window, NG_VERSIONS) {
$scope.docs_versions = NG_VERSIONS;
$scope.docs_version = NG_VERSIONS[0];
for(var i=0, minor = NaN; i < NG_VERSIONS.length; i++) {
var version = NG_VERSIONS[i];
// NaN will give false here
if (minor <= version.minor) {
continue;
}
version.isLatest = true;
minor = version.minor;
}
$scope.docs_versions = NG_VERSIONS;
$scope.getGroupName = function(v) {
return v.isLatest ? 'Latest' : (v.isStable ? 'Stable' : 'Unstable');
};
$scope.jumpToDocsVersion = function(version) {
var currentPagePath = $location.path();
// TODO: We need to do some munging of the path for different versions of the API...
$window.location = version.docsUrl + currentPagePath;
};
}]);
}]);
+1 -1
View File
@@ -31,4 +31,4 @@ describe("DocsController", function() {
expect($window._gaq.pop()).toEqual(['_trackPageview', 'x/y/z']);
}));
});
});
});
+10
View File
@@ -0,0 +1,10 @@
{
"name": "AngularJS-docs-app",
"dependencies": {
"jquery": "2.1.1",
"lunr.js": "0.4.3",
"open-sans-fontface": "1.0.4",
"google-code-prettify": "1.0.1",
"bootstrap": "3.1.1"
}
}
+3 -2
View File
@@ -9,7 +9,7 @@ module.exports = function(config) {
config = basePackage(config);
config = examplesPackage(config);
config.append('processing.processors', [
require('./processors/git-data'),
require('./processors/error-docs'),
@@ -22,7 +22,8 @@ module.exports = function(config) {
]);
config.append('processing.tagDefinitions', [
require('./tag-defs/tutorial-step')
require('./tag-defs/tutorial-step'),
require('./tag-defs/sortOrder')
]);
config.append('processing.defaultTagTransforms', [
+1 -1
View File
@@ -30,4 +30,4 @@ function writeFile(file, content) {
return fs.makeTree(fs.directory(file)).then(function() {
return fs.write(file, content, 'wb');
});
}
}
+1 -1
View File
@@ -56,4 +56,4 @@ module.exports = {
return docs.concat(_.values(errorNamespaces));
}
};
};
+1 -1
View File
@@ -17,4 +17,4 @@ module.exports = {
process: function(extraData, gitData) {
extraData.git = gitData;
}
};
};
+16 -4
View File
@@ -1,3 +1,4 @@
"use strict";
var _ = require('lodash');
var log = require('winston');
var fs = require('fs');
@@ -5,7 +6,7 @@ var path = require('canonical-path');
module.exports = {
name: 'keywords',
runAfter: ['docs-processed'],
runAfter: ['docs-processed', 'api-docs'],
runBefore: ['adding-extra-docs'],
description: 'This processor extracts all the keywords from the document',
process: function(docs, config) {
@@ -52,7 +53,7 @@ module.exports = {
_.forEach(tokens, function(token){
var match = token.match(KEYWORD_REGEX);
if (match){
key = match[1];
var key = match[1];
if ( !keywordMap[key]) {
keywordMap[key] = true;
words.push(key);
@@ -69,20 +70,31 @@ module.exports = {
var words = [];
var keywordMap = _.clone(ignoreWordsMap);
var members = [];
var membersMap = {};
// Search each top level property of the document for search terms
_.forEach(doc, function(value, key) {
if ( _.isString(value) && !propertiesToIgnore[key] ) {
extractWords(value, words, keywordMap);
}
if ( key === 'methods' || key === 'properties' || key === 'events' ) {
_.forEach(value, function(member) {
extractWords(member.name, members, membersMap);
});
}
});
doc.searchTerms = {
titleWords: extractTitleWords(doc.name),
keywords: _.sortBy(words).join(' ')
keywords: _.sortBy(words).join(' '),
members: _.sortBy(members).join(' ')
};
});
}
};
};
+14 -7
View File
@@ -119,13 +119,20 @@ var navGroupMappers = {
})];
},
pages: function(pages, area) {
return [getNavGroup(pages, area, 'path', function(page) {
return {
name: page.name,
href: page.path,
type: 'page'
};
})];
return [getNavGroup(
pages,
area,
function(page) {
return page.sortOrder || page.path;
},
function(page) {
return {
name: page.name,
href: page.path,
type: 'page'
};
}
)];
}
};
@@ -33,7 +33,8 @@ module.exports = {
innerTest: file.fileContents,
pathPrefix: '.', // Hold for if we test with full jQuery
exampleId: example.id,
description: example.doc.id
description: example.doc.id,
'ng-app-included': example['ng-app-included']
};
if (env === 'jquery') {
+1 -1
View File
@@ -35,4 +35,4 @@ module.exports = {
docs.push(versionDoc);
}
};
};
+6
View File
@@ -0,0 +1,6 @@
module.exports = {
name: 'sortOrder',
transforms: function(doc, tag, value) {
return parseInt(value, 10);
}
};
+1 -1
View File
@@ -14,4 +14,4 @@
{$ doc.description | marked $}
</div>
{% endblock %}
{% endblock %}
@@ -25,4 +25,4 @@
</div>
</div>
{% endblock %}
{% endblock %}
@@ -175,7 +175,7 @@
<div class="container main-grid main-header-grid">
<div class="grid-left">
<div ng-controller="DocsVersionsCtrl" class="picker version-picker">
<select ng-options="v as ('v' + v.version + (v.isSnapshot ? ' (snapshot)' : '')) group by (v.isStable?'Stable':'Unstable') for v in docs_versions"
<select ng-options="v as ('v' + v.version + (v.isSnapshot ? ' (snapshot)' : '')) group by getGroupName(v) for v in docs_versions"
ng-model="docs_version"
ng-change="jumpToDocsVersion(docs_version)"
class="docs-version-jump">
@@ -1,7 +1,10 @@
describe("{$ doc.description $}", function() {
var rootEl;
beforeEach(function() {
rootEl = browser.rootEl;{% if doc['ng-app-included'] %}
browser.rootEl = '[ng-app]';{% endif %}
browser.get("{$ doc.pathPrefix $}/{$ doc.examplePath $}");
});
{% if doc['ng-app-included'] %}afterEach(function() { browser.rootEl = rootEl; });{% endif %}
{$ doc.innerTest $}
});
});
@@ -24,4 +24,4 @@
</div>
{# Be aware that we need these extra new lines here or marked will not realise that the <div>
above is HTML and wrap each line in a <p> - thus breaking the HTML #}
above is HTML and wrap each line in a <p> - thus breaking the HTML #}
+1 -1
View File
@@ -1 +1 @@
{% include 'overview.template.html' %}
{% include 'overview.template.html' %}
+1 -1
View File
@@ -23,4 +23,4 @@ When an instance of `MyCtrl` is created, the service `myService` will be created
by the `$injector`. `myService` depends on itself, which causes the `$injector`
to detect a circular dependency and throw the error.
For more information, see the {@link guide/di Dependency Injection Guide}.
For more information, see the {@link guide/di Dependency Injection Guide}.
+1 -1
View File
@@ -23,4 +23,4 @@ To avoid the error, always use string literals for dependency injection annotati
tokens.
For an explanation of what injection annotations are and how to use them, refer
to the {@link guide/di Dependency Injection Guide}.
to the {@link guide/di Dependency Injection Guide}.
+1 -1
View File
@@ -23,4 +23,4 @@ angular.module("myApp", [])
```
For more information, refer to the {@link auto.$provide#provider
$provide.provider} api doc.
$provide.provider} api doc.
+31 -1
View File
@@ -14,7 +14,7 @@ angular.module('myApp', [])
}]);
```
The above code will fail with `$injector:unpr` if `myService` is not defined.
The above code will fail with `$injector:unpr` if `myService` is not defined.
Making sure each dependency is defined will fix the problem, as noted below.
@@ -25,3 +25,33 @@ angular.module('myApp', [])
// Do something with myService
}]);
```
An unknown provider error can also be caused by accidentally redefining a
module using the `angular.module` API, as shown in the following example.
```
angular.module('myModule', [])
.service('myCoolService', function () { /* ... */ });
angular.module('myModule', [])
// myModule has already been created! This is not what you want!
.directive('myDirective', ['myCoolService', function (myCoolService) {
// This directive definition throws unknown provider, because myCoolService
// has been destroyed.
}]);
```
To fix this problem, make sure you only define each module with the
`angular.module(name, [requires])` syntax once across your entire project.
Retrieve it for subsequent use with `angular.module(name)`. The fixed example
is shown below.
```
angular.module('myModule', [])
.service('myCoolService', function () { /* ... */ });
angular.module('myModule')
.directive('myDirective', ['myCoolService', function (myCoolService) {
// This directive definition does not throw unknown provider.
}]);
```
@@ -9,4 +9,4 @@ it hard to reason about whether some combination of concatenated values are
unsafe to use and could easily lead to XSS.
For more information about how AngularJS helps keep your app secure, refer to
the {@link ng.$sce $sce} API doc.
the {@link ng.$sce $sce} API doc.
+51
View File
@@ -0,0 +1,51 @@
@ngdoc error
@name $location:nobase
@fullName $location in HTML5 mode requires a <base> tag to be present!
@description
If you configure {@link ng.$location `$location`} to use
{@link api/ng.provider.$locationProvider `html5Mode`} (`history.pushState`), you need to specify the base URL for the application with a [`<base href="">`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base) tag.
The base URL is then used to resolve all relative URLs throughout the application regardless of the
entry point into the app.
If you are deploying your app into the root context (e.g. `https://myapp.com/`), set the base URL to `/`:
```html
<head>
<base href="/">
...
</head>
```
If you are deploying your app into a sub-context (e.g. `https://myapp.com/subapp/`), set the base URL to the
URL of the subcontext:
```html
<head>
<base href="/subapp">
...
</head>
```
Before Angular 1.3 we didn't have this hard requirement and it was easy to write apps that worked
when deployed in the root context but were broken when moved to a sub-context because in the
sub-context all absolute urls would resolve to the root context of the app. To prevent this,
use relative URLs throughout your app:
```html
<!-- wrong: -->
<a href="/userProfile">User Profile</a>
<!-- correct: -->
<a href="userProfile">User Profile</a>
```
Additionally, if you want to support [browsers that don't have the `history.pushState`
API](http://caniuse.com/#feat=history), the fallback mechanism provided by `$location`
won't work well without specifying the base url of the application.
In order to make it easier to migrate from hashbang mode to html5 mode, we require that the base
URL is always specified when `$location`'s `html5mode` is enabled.
+31
View File
@@ -14,3 +14,34 @@ perform this check - it's up to the developer to not expose such sensitive and p
directly on the scope chain.
To resolve this error, avoid access to DOM nodes.
# Event Handlers and Return Values
The `$parse:isecdom` error also occurs when an event handler invokes a function that returns a DOM
node.
```html
<button ng-click="iWillReturnDOM()">click me</button>
```
```js
$scope.iWillReturnDOM = function() {
return someDomNode;
}
```
To fix this issue, avoid returning DOM nodes from event handlers.
*Note: This error often means that you are accessing DOM from your controllers, which is usually
a sign of poor coding style that violates separation of concerns.*
# Implicit Returns in CoffeeScript
This error can occur more frequently when using CoffeeScript, which has a feature called implicit
returns. This language feature returns the last dereferenced object in the function when the
function has no explicit return statement.
The solution in this scenario is to add an explicit return statement. For example `return false` to
the function.
+17
View File
@@ -0,0 +1,17 @@
@ngdoc error
@name $parse:isecff
@fullName Referencing 'call', 'apply' and 'bind' Disallowed
@description
Occurs when an expression attempts to invoke Function's 'call', 'apply' or 'bind'.
Angular bans the invocation of 'call', 'apply' and 'bind' from within expressions
since access is a known way to modify the behaviour of existing functions.
To resolve this error, avoid using these methods in expressions.
Example expression that would result in this error:
```
<div>{{user.sendInfo.call({}, true)}}</div>
```
+17 -8
View File
@@ -1,18 +1,27 @@
@ngdoc error
@name $parse:isecfld
@fullName Referencing 'constructor' Field in Expression
@fullName Referencing Disallowed Field in Expression
@description
Occurs when an expression attempts to access an objects constructor field.
Occurs when an expression attempts to access one of the following fields:
AngularJS bans constructor access from within expressions since constructor
access is a known way to execute arbitrary Javascript code.
* __proto__
* __defineGetter__
* __defineSetter__
* __lookupGetter__
* __lookupSetter__
To resolve this error, avoid constructor access. As a last resort, alias
the constructor and access it through the alias instead.
AngularJS bans access to these fields from within expressions since
access is a known way to mess with native objects or
to execute arbitrary Javascript code.
Example expression that would result in this error:
To resolve this error, avoid using these fields in expressions. As a last resort,
alias their value and access them through the alias instead.
Example expressions that would result in this error:
```
<div>{{user.constructor.name}}</div>
<div>{{user.__proto__.hasOwnProperty = $emit}}</div>
<div>{{user.__defineGetter__('name', noop)}}</div>
```
+11
View File
@@ -0,0 +1,11 @@
@ngdoc error
@name $parse:isecobj
@fullName Referencing Object Disallowed
@description
Occurs when an expression attempts to access the 'Object' object (Root object in JavaScript).
Angular bans access to Object from within expressions since access is a known way to modify
the behaviour of existing objects.
To resolve this error, avoid Object access.
+17
View File
@@ -0,0 +1,17 @@
@ngdoc error
@name $q:norslvr
@fullName No resolver function passed to $Q
@description
Occurs when calling creating a promise using {@link $q} as a constructor, without providing the
required `resolver` function.
```
//bad
var promise = $q().then(doSomething);
//good
var promise = $q(function(resolve, reject) {
waitForSomethingAsync.then(resolve);
}).then(doSomething);
```
+23
View File
@@ -0,0 +1,23 @@
@ngdoc error
@name $q:qcycle
@fullName Cannot resolve a promise with itself
@description
Occurs when resolving a promise with itself as the value, including returning the promise in a
function passed to `then`. The A+ 1.1 spec mandates that this behavior throw a TypeError.
https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure
```
var promise = $q.defer().promise;
//bad
promise.then(function (val) {
//Cannot return self
return promise;
});
//good
promise.then(function (val) {
return 'some other value';
});
```
+1 -1
View File
@@ -5,4 +5,4 @@
Occurs when you try to use the name `hasOwnProperty` as a name of a parameter.
Generally, a name cannot be `hasOwnProperty` because it is used, internally, on a object
and allowing such a name would break lookups on this object.
and allowing such a name would break lookups on this object.
+1 -1
View File
@@ -161,7 +161,7 @@ In this second scenario, we are already inside a `$digest` when the ngFocus dire
call to `$apply()`, causing this error to be thrown.
It is possible to workaround this problem by moving the call to set the focus outside of the digest,
by using `$timeOut(fn, 0, false)`, where the `false` value tells Angular not to wrap this `fn` in a
by using `$timeout(fn, 0, false)`, where the `false` value tells Angular not to wrap this `fn` in a
`$apply` block:
```
+3 -3
View File
@@ -15,9 +15,9 @@ By default, only URLs that belong to the same origin are trusted. These are urls
The {@link ng.directive:ngInclude ngInclude} directive and {@link guide/directive directives} that specify a `templateUrl` require a trusted resource URL.
To load templates from other domains and/or protocols, either adjust the {@link
api/ng.$sceDelegateProvider#resourceUrlWhitelist whitelist}/ {@link
api/ng.$sceDelegateProvider#resourceUrlBlacklist blacklist} or wrap the URL with a call to {@link
api/ng.$sce#trustAsResourceUrl $sce.trustAsResourceUrl}.
ng.$sceDelegateProvider#resourceUrlWhitelist whitelist}/ {@link
ng.$sceDelegateProvider#resourceUrlBlacklist blacklist} or wrap the URL with a call to {@link
ng.$sce#trustAsResourceUrl $sce.trustAsResourceUrl}.
**Note**: The browser's [Same Origin
Policy](https://code.google.com/p/browsersec/wiki/Part2#Same-origin_policy_for_XMLHttpRequest) and
+2 -2
View File
@@ -10,7 +10,7 @@ Angular's {@link ng.$sce Strict Contextual Escaping (SCE)} mode
contexts to result in a value that is trusted as safe for use in such a context. (e.g. loading an
Angular template from a URL requires that the URL is one considered safe for loading resources.)
This helps prevent XSS and other security issues. Read more at {@link
api/ng.$sce Strict Contextual Escaping (SCE)}
This helps prevent XSS and other security issues. Read more at
{@link ng.$sce Strict Contextual Escaping (SCE)}
You may want to include the ngSanitize module to use the automatic sanitizing.
+1 -1
View File
@@ -5,4 +5,4 @@
AngularJS often asserts that certain values will be present and truthy using a
helper function. If the assertion fails, this error is thrown. To fix this problem,
make sure that the value the assertion expects is defined and truthy.
make sure that the value the assertion expects is defined and truthy.
+1 -1
View File
@@ -5,4 +5,4 @@
Occurs when you try to use the name `hasOwnProperty` in a context where it is not allow.
Generally, a name cannot be `hasOwnProperty` because it is used, internally, on a object
and allowing such a name would break lookups on this object.
and allowing such a name would break lookups on this object.
+1 -1
View File
@@ -49,4 +49,4 @@ You can also get this error if you accidentally load AngularJS itself more than
<script src="angular.js"></script>
</body>
</html>
```
```
+1 -1
View File
@@ -7,4 +7,4 @@ This error occurs when attempting to copy an object to itself. Calling {@link
api/angular.copy angular.copy} with a `destination` object deletes
all of the elements or properties on `destination` before copying to it. Copying
an object to itself is not supported. Make sure to check your calls to
`angular.copy` and avoid copying objects or arrays to themselves.
`angular.copy` and avoid copying objects or arrays to themselves.
+1 -1
View File
@@ -7,4 +7,4 @@ Copying Window or Scope instances is not supported because of cyclical and self
references. Avoid copying windows and scopes, as well as any other cyclical or
self-referential structures. Note that trying to deep copy an object containing
cyclical references that is neither a window nor a scope will cause infinite
recursion and a stack overflow.
recursion and a stack overflow.
@@ -0,0 +1,21 @@
@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}">
```
@@ -0,0 +1,39 @@
@ngdoc error
@name ngRepeat:badident
@fullName Invalid identifier expression
@description
Occurs when an invalid identifier is specified in an {@link ng.directive:ngRepeat ngRepeat} expression.
The {@link ng.directive:ngRepeat ngRepeat} directive's `alias as` syntax is used to assign an alias for the processed collection in scope.
If the expression is not a simple identifier (such that you could declare it with `var {name}`, or if the expression is a reserved name,
this error is thrown.
Reserved names include:
- `null`
- `this`
- `undefined`
- `$parent`
- `$even`
- `$odd`
- `$first`
- `$last`
- `$middle`
Invalid expressions might look like this:
```html
<li ng-repeat="item in items | filter:searchString as this">{{item}}</li>
<li ng-repeat="item in items | filter:searchString as some.objects["property"]">{{item}}</li>
<li ng-repeat="item in items | filter:searchString as resultOfSomeMethod()">{{item}}</li>
<li ng-repeat="item in items | filter:searchString as foo=6">{{item}}</li>
```
Valid expressions might look like this:
```html
<li ng-repeat="item in items | filter:searchString as collections">{{item}}</li>
<li ng-repeat="item in items | filter:searchString as filteredCollection">{{item}}</li>
```
+321 -133
View File
@@ -1,5 +1,6 @@
@ngdoc overview
@name Using $location
@sortOrder 500
@description
# What does it do?
@@ -60,7 +61,7 @@ changes to $location are reflected into the browser address bar.
<tr>
<td class="head">aware of docroot/context from which the application is loaded</td>
<td>no - window.location.path returns "/docroot/actual/path"</td>
<td>no - window.location.pathname returns "/docroot/actual/path"</td>
<td>yes - $location.path() returns "/actual/path"</td>
</tr>
@@ -210,6 +211,10 @@ facilitate the browser URL change and history management.
## Hashbang mode (default mode)
In this mode, `$location` uses Hashbang URLs in all browsers.
Angular also does not intercept and rewrite links in this mode. I.e. links work
as expected and also perform full page reloads when other parts of the url
than the hash fragment was changed.
### Example
@@ -249,6 +254,10 @@ having to worry about whether the browser displaying your app supports the histo
- Opening a regular URL in a legacy browser -> redirects to a hashbang URL
- Opening hashbang URL in a modern browser -> rewrites to a regular URL
Note that in this mode, Angular intercepts all links (subject to the "Html link rewriting" rules below)
and updates the url in a way that never performs a full page reload.
### Example
```js
@@ -297,8 +306,8 @@ history API or not; the `$location` service makes this transparent to you.
### Html link rewriting
When you use HTML5 history API mode, you will need different links in different browsers, but all you
have to do is specify regular URL links, such as: `<a href="/some?foo=bar">link</a>`
When you use HTML5 history API mode, you will not need special hashbang links. All you have to do
is specify regular URL links, such as: `<a href="/some?foo=bar">link</a>`
When a user clicks on this link,
@@ -313,32 +322,26 @@ reload to the original link.
Example: `<a href="/ext/link?a=b" target="_self">link</a>`
- Absolute links that go to a different domain<br>
Example: `<a href="http://angularjs.org/">link</a>`
- Links starting with '/' that lead to a different base path when base is defined<br>
- Links starting with '/' that lead to a different base path<br>
Example: `<a href="/not-my-base/link">link</a>`
When running Angular in the root of a domain, along side perhaps a normal application in the same
directory, the "otherwise" route handler will try to handle all the URLs, including ones that map
to static files.
To prevent this, you can set your base href for the app to `<base href=".">` and then prefix links
to URLs that should be handled with `.`. Now, links to locations, which are not to be routed by Angular,
are not prefixed with `.` and will not be intercepted by the `otherwise` rule in your `$routeProvider`.
### Relative links
Be sure to check all relative links, images, scripts etc. Angular requires you to specify the url base in
the head of your main html file (`<base href="/my-base">`). With that, relative urls will
always be resolved to this base url, event if the initial url of the document was different.
There is one exception: Links that only contain a hash fragment (e.g. `<a href="#target">`)
will only change `$location.hash()` and not modify the url otherwise. This is useful for scrolling
to anchors on the same page without needing to know on which page the user currently is.
### Server side
Using this mode requires URL rewriting on server side, basically you have to rewrite all your links
to entry point of your application (e.g. index.html)
### Relative links
Be sure to check all relative links, images, scripts etc. You must either specify the url base in
the head of your main html file (`<base href="/my-base">`) or you must use absolute urls
(starting with `/`) everywhere because relative urls will be resolved to absolute urls using the
initial absolute url of the document, which is often different from the root of the application.
Running Angular apps with the History API enabled from document root is strongly encouraged as it
takes care of all relative link issues.
to entry point of your application (e.g. index.html). Requiring a `<base>` tag is also important for
this case, as it allows Angular to differentiate between the part of the url that is the application
base and the path that should be handeled by the application.
### Sending links among different browsers
@@ -358,118 +361,308 @@ Note that when you type hashbang url into first browser (or vice versa) it doesn
redirect to regular / hashbang url, as this conversion happens only during parsing the initial URL
= on page reload.
In this examples we use `<base href="/base/index.html" />`
<example>
In these examples we use `<base href="/base/index.html" />`
#### Browser in HTML5 mode
<example module="html5-mode" name="location-html5-mode">
<file name="index.html">
<div id="html5-mode" ng-controller="Html5Cntl">
<h3>Browser with History API</h3>
<div ng-address-bar browser="html5"></div><br><br>
$location.protocol() = {{$location.protocol()}}<br>
$location.host() = {{$location.host()}}<br>
$location.port() = {{$location.port()}}<br>
$location.path() = {{$location.path()}}<br>
$location.search() = {{$location.search()}}<br>
$location.hash() = {{$location.hash()}}<br>
<a href="http://www.example.com/base/first?a=b">/base/first?a=b</a> |
<a href="http://www.example.com/base/sec/ond?flag#hash">sec/ond?flag#hash</a> |
<a href="/other-base/another?search">external</a>
</div>
<div id="hashbang-mode" ng-controller="HashbangCntl">
<h3>Browser without History API</h3>
<div ng-address-bar browser="hashbang"></div><br><br>
$location.protocol() = {{$location.protocol()}}<br>
$location.host() = {{$location.host()}}<br>
$location.port() = {{$location.port()}}<br>
$location.path() = {{$location.path()}}<br>
$location.search() = {{$location.search()}}<br>
$location.hash() = {{$location.hash()}}<br>
<a href="http://www.example.com/base/first?a=b">/base/first?a=b</a> |
<a href="http://www.example.com/base/sec/ond?flag#hash">sec/ond?flag#hash</a> |
<a href="/other-base/another?search">external</a>
<div ng-controller="LocationController">
<div ng-address-bar></div><br><br>
<div>
$location.protocol() = <span ng-bind="$location.protocol()"></span> <br>
$location.host() = <span ng-bind="$location.host()"></span> <br>
$location.port() = <span ng-bind="$location.port()"></span> <br>
$location.path() = <span ng-bind="$location.path()"></span> <br>
$location.search() = <span ng-bind="$location.search()"></span> <br>
$location.hash() = <span ng-bind="$location.hash()"></span> <br>
</div>
<div id="navigation">
<a href="http://www.example.com/base/first?a=b">/base/first?a=b</a> |
<a href="http://www.example.com/base/sec/ond?flag#hash">sec/ond?flag#hash</a> |
<a href="/other-base/another?search">external</a>
</div>
</div>
</file>
<file name="app.js">
angular.module('html5-mode', ['fake-browser', 'address-bar'])
<file name="script.js">
function FakeBrowser(initUrl, baseHref) {
this.onUrlChange = function(fn) {
this.urlChange = fn;
.constant('initUrl', 'http://www.example.com/base/path?a=b#h')
.constant('baseHref', '/base/index.html')
.value('$sniffer', { history: true })
.controller("LocationController", function($scope, $location) {
$scope.$location = {};
angular.forEach("protocol host port path search hash".split(" "), function(method){
$scope.$location[method] = function(){
var result = $location[method].call($location);
return angular.isObject(result) ? angular.toJson(result) : result;
};
});
})
.config(function($locationProvider) {
$locationProvider.html5Mode(true).hashPrefix('!');
})
.run(function($rootElement) {
$rootElement.on('click', function(e) { e.stopPropagation(); });
});
</file>
<file name="fakeBrowser.js">
angular.module('fake-browser', [])
.config(function($provide) {
$provide.decorator('$browser', function($delegate, baseHref, initUrl) {
$delegate.onUrlChange = function(fn) {
this.urlChange = fn;
};
$delegate.url = function() {
return initUrl;
};
this.url = function() {
return initUrl;
};
$delegate.defer = function(fn, delay) {
setTimeout(function() { fn(); }, delay || 0);
};
this.defer = function(fn, delay) {
setTimeout(function() { fn(); }, delay || 0);
};
$delegate.baseHref = function() {
return baseHref;
};
this.baseHref = function() {
return baseHref;
};
return $delegate;
});
});
</file>
this.notifyWhenOutstandingRequests = angular.noop;
}
<file name="addressBar.js">
angular.module('address-bar', [])
.directive('ngAddressBar', function($browser, $timeout) {
return {
template: 'Address: <input id="addressBar" type="text" style="width: 400px" >',
link: function(scope, element, attrs){
var input = element.children("input"), delay;
var browsers = {
html5: new FakeBrowser('http://www.example.com/base/path?a=b#h', '/base/index.html'),
hashbang: new FakeBrowser('http://www.example.com/base/index.html#!/path?a=b#h', '/base/index.html')
};
input.on('keypress keyup keydown', function(event) {
delay = (!delay ? $timeout(fireUrlChange, 250) : null);
event.stopPropagation();
})
.val($browser.url());
function Html5Cntl($scope, $location) {
$scope.$location = $location;
}
function HashbangCntl($scope, $location) {
$scope.$location = $location;
}
function initEnv(name) {
var root = angular.element(document.getElementById(name + '-mode'));
// We must kill a link to the injector for this element otherwise angular will
// complain that it has been bootstrapped already.
root.data('$injector', null);
angular.bootstrap(root, [function($compileProvider, $locationProvider, $provide){
$locationProvider.html5Mode(true).hashPrefix('!');
$provide.value('$browser', browsers[name]);
$provide.value('$sniffer', {history: name == 'html5'});
$compileProvider.directive('ngAddressBar', function() {
return function(scope, elm, attrs) {
var browser = browsers[attrs.browser],
input = angular.element('<input type="text" style="width: 400px">').val(browser.url()),
delay;
input.on('keypress keyup keydown', function() {
if (!delay) {
delay = setTimeout(fireUrlChange, 250);
}
});
browser.url = function(url) {
return input.val(url);
};
elm.append('Address: ').append(input);
function fireUrlChange() {
delay = null;
browser.urlChange(input.val());
}
$browser.url = function(url) {
return url ? input.val(url) : input.val();
};
});
}]);
root.on('click', function(e) {
e.stopPropagation();
});
}
initEnv('html5');
initEnv('hashbang');
function fireUrlChange() {
delay = null;
$browser.urlChange(input.val());
}
}
};
});
</file>
<file name="protractor.js" type="protractor">
var addressBar = element(by.css("#addressBar")),
url = 'http://www.example.com/base/path?a=b#h';
it("should show fake browser info on load", function(){
expect(addressBar.getAttribute('value')).toBe(url);
expect(element(by.binding('$location.protocol()')).getText()).toBe('http');
expect(element(by.binding('$location.host()')).getText()).toBe('www.example.com');
expect(element(by.binding('$location.port()')).getText()).toBe('80');
expect(element(by.binding('$location.path()')).getText()).toBe('/path');
expect(element(by.binding('$location.search()')).getText()).toBe('{"a":"b"}');
expect(element(by.binding('$location.hash()')).getText()).toBe('h');
});
it("should change $location accordingly", function(){
var navigation = element.all(by.css("#navigation a"));
navigation.get(0).click();
expect(addressBar.getAttribute('value')).toBe("http://www.example.com/base/first?a=b");
expect(element(by.binding('$location.protocol()')).getText()).toBe('http');
expect(element(by.binding('$location.host()')).getText()).toBe('www.example.com');
expect(element(by.binding('$location.port()')).getText()).toBe('80');
expect(element(by.binding('$location.path()')).getText()).toBe('/first');
expect(element(by.binding('$location.search()')).getText()).toBe('{"a":"b"}');
expect(element(by.binding('$location.hash()')).getText()).toBe('');
navigation.get(1).click();
expect(addressBar.getAttribute('value')).toBe("http://www.example.com/base/sec/ond?flag#hash");
expect(element(by.binding('$location.protocol()')).getText()).toBe('http');
expect(element(by.binding('$location.host()')).getText()).toBe('www.example.com');
expect(element(by.binding('$location.port()')).getText()).toBe('80');
expect(element(by.binding('$location.path()')).getText()).toBe('/sec/ond');
expect(element(by.binding('$location.search()')).getText()).toBe('{"flag":true}');
expect(element(by.binding('$location.hash()')).getText()).toBe('hash');
});
</file>
</example>
####Browser in HTML5 Fallback mode (Hashbang mode)
<example module="hashbang-mode" name="location-hashbang-mode">
<file name="index.html">
<div ng-controller="LocationController">
<div ng-address-bar></div><br><br>
<div>
$location.protocol() = <span ng-bind="$location.protocol()"></span> <br>
$location.host() = <span ng-bind="$location.host()"></span> <br>
$location.port() = <span ng-bind="$location.port()"></span> <br>
$location.path() = <span ng-bind="$location.path()"></span> <br>
$location.search() = <span ng-bind="$location.search()"></span> <br>
$location.hash() = <span ng-bind="$location.hash()"></span> <br>
</div>
<div id="navigation">
<a href="http://www.example.com/base/first?a=b">/base/first?a=b</a> |
<a href="http://www.example.com/base/sec/ond?flag#hash">sec/ond?flag#hash</a> |
<a href="/other-base/another?search">external</a>
</div>
</div>
</file>
<file name="app.js">
angular.module('hashbang-mode', ['fake-browser', 'address-bar'])
.constant('initUrl', 'http://www.example.com/base/index.html#!/path?a=b#h')
.constant('baseHref', '/base/index.html')
.value('$sniffer', { history: false })
.config(function($locationProvider) {
$locationProvider.html5Mode(true).hashPrefix('!');
})
.controller("LocationController", function($scope, $location) {
$scope.$location = {};
angular.forEach("protocol host port path search hash".split(" "), function(method){
$scope.$location[method] = function(){
var result = $location[method].call($location);
return angular.isObject(result) ? angular.toJson(result) : result;
};
});
})
.run(function($rootElement) {
$rootElement.on('click', function(e) {
e.stopPropagation();
});
});
</file>
<file name="fakeBrowser.js">
angular.module('fake-browser', [])
.config(function($provide) {
$provide.decorator('$browser', function($delegate, baseHref, initUrl) {
$delegate.onUrlChange = function(fn) {
this.urlChange = fn;
};
$delegate.url = function() {
return initUrl;
};
$delegate.defer = function(fn, delay) {
setTimeout(function() { fn(); }, delay || 0);
};
$delegate.baseHref = function() {
return baseHref;
};
return $delegate;
});
});
</file>
<file name="addressBar.js">
angular.module('address-bar', [])
.directive('ngAddressBar', function($browser, $timeout) {
return {
template: 'Address: <input id="addressBar" type="text" style="width: 400px" >',
link: function(scope, element, attrs){
var input = element.children("input"), delay;
input.on('keypress keyup keydown', function(event) {
delay = (!delay ? $timeout(fireUrlChange, 250) : null);
event.stopPropagation();
})
.val($browser.url());
$browser.url = function(url) {
return url ? input.val(url) : input.val();
};
function fireUrlChange() {
delay = null;
$browser.urlChange(input.val());
}
}
};
});
</file>
<file name="protractor.js" type="protractor">
var addressBar = element(by.css("#addressBar")),
url = 'http://www.example.com/base/index.html#!/path?a=b#h';
it("should show fake browser info on load", function(){
expect(addressBar.getAttribute('value')).toBe(url);
expect(element(by.binding('$location.protocol()')).getText()).toBe('http');
expect(element(by.binding('$location.host()')).getText()).toBe('www.example.com');
expect(element(by.binding('$location.port()')).getText()).toBe('80');
expect(element(by.binding('$location.path()')).getText()).toBe('/path');
expect(element(by.binding('$location.search()')).getText()).toBe('{"a":"b"}');
expect(element(by.binding('$location.hash()')).getText()).toBe('h');
});
it("should change $location accordingly", function(){
var navigation = element.all(by.css("#navigation a"));
navigation.get(0).click();
expect(addressBar.getAttribute('value')).toBe("http://www.example.com/base/index.html#!/first?a=b");
expect(element(by.binding('$location.protocol()')).getText()).toBe('http');
expect(element(by.binding('$location.host()')).getText()).toBe('www.example.com');
expect(element(by.binding('$location.port()')).getText()).toBe('80');
expect(element(by.binding('$location.path()')).getText()).toBe('/first');
expect(element(by.binding('$location.search()')).getText()).toBe('{"a":"b"}');
expect(element(by.binding('$location.hash()')).getText()).toBe('');
navigation.get(1).click();
expect(addressBar.getAttribute('value')).toBe("http://www.example.com/base/index.html#!/sec/ond?flag#hash");
expect(element(by.binding('$location.protocol()')).getText()).toBe('http');
expect(element(by.binding('$location.host()')).getText()).toBe('www.example.com');
expect(element(by.binding('$location.port()')).getText()).toBe('80');
expect(element(by.binding('$location.path()')).getText()).toBe('/sec/ond');
expect(element(by.binding('$location.search()')).getText()).toBe('{"flag":true}');
expect(element(by.binding('$location.hash()')).getText()).toBe('hash');
});
</file>
</example>
# Caveats
@@ -618,27 +811,22 @@ then uses the information it obtains to compose hashbang URLs (such as
## Two-way binding to $location
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>
Because `$location` uses getters/setters, you can use `ng-model-options="{ getterSetter: true }"`
to bind it to `ngModel`:
<example module="locationExample">
<file name="index.html">
<div ng-controller="LocationController">
<input type="text" ng-model="locationPath" />
<input type="text" ng-model="locationPath" ng-model-options="{ getterSetter: true }" />
</div>
</file>
<file name="script.js">
function LocationController($scope, $location) {
$scope.$watch('locationPath', function(path) {
$location.path(path);
});
$scope.$watch(function() {
return $location.path();
}, function(path) {
$scope.locationPath = path;
});
}
angular.module('locationExample', [])
.controller('LocationController', ['$scope', '$location', function($scope, $location) {
$scope.locationPath = function (newLocation) {
return $location.path(newLocation);
};
}]);
</file>
</example>
+3 -11
View File
@@ -1,5 +1,6 @@
@ngdoc overview
@name Animations
@sortOrder 310
@description
@@ -33,23 +34,14 @@ Below is a quick example of animations being enabled for `ngShow` and `ngHide`:
background:white;
}
.sample-show-hide.ng-hide-add, .sample-show-hide.ng-hide-remove {
.sample-show-hide {
-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-add.ng-hide-add-active,
.sample-show-hide.ng-hide-remove {
.sample-show-hide.ng-hide {
opacity:0;
}
.sample-show-hide.ng-hide-add,
.sample-show-hide.ng-hide-remove.ng-hide-remove-active {
opacity:1;
}
</file>
</example>
+3 -6
View File
@@ -1,5 +1,6 @@
@ngdoc overview
@name Bootstrap
@sortOrder 350
@description
# Bootstrap
@@ -38,11 +39,7 @@ initialization.
<html ng-app>
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`
3. 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:`.)
@@ -90,7 +87,7 @@ Here is an example of manually initializing Angular:
<!doctype html>
<html>
<body>
Hello {{'World'}}!
Hello {{greetMe}}!
<script src="http://code.angularjs.org/snapshot/angular.js"></script>
<script>
+4 -3
View File
@@ -1,5 +1,6 @@
@ngdoc overview
@name HTML Compiler
@sortOrder 330
@description
<div class="alert alert-warning">
@@ -198,7 +199,7 @@ This should help give you an idea of what Angular does internally.
// Step 3: link the compiled template with the scope.
var element = linkFn(scope);
// Step 4: Append to DOM (optional)
parent.appendChild(element);
```
@@ -226,7 +227,7 @@ moved to the compile function for performance reasons.
To understand, let's look at a real-world example with `ngRepeat`:
```html
Hello {{user}}, you have these actions:
Hello {{user.name}}, you have these actions:
<ul>
<li ng-repeat="action in user.actions">
{{action.description}}
@@ -236,7 +237,7 @@ Hello {{user}}, you have these actions:
When the above example is compiled, the compiler visits every node and looks for directives.
`{{user}}` matches the {@link ng.$interpolate interpolation directive}
`{{user.name}}` matches the {@link ng.$interpolate interpolation directive}
and `ng-repeat` matches the {@link ng.directive:ngRepeat `ngRepeat` directive}.
But {@link ng.directive:ngRepeat ngRepeat} has a dilemma.
+12 -14
View File
@@ -1,5 +1,6 @@
@ngdoc overview
@name Conceptual Overview
@sortOrder 200
@description
# Conceptual Overview
@@ -37,10 +38,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" ng-model="qty" required >
Quantity: <input type="number" min="0" ng-model="qty">
</div>
<div>
Costs: <input type="number" ng-model="cost" required >
Costs: <input type="number" min="0" ng-model="cost">
</div>
<div>
<b>Total:</b> {{qty * cost | currency}}
@@ -62,11 +63,8 @@ The first kind of new markup are the so called <a name="directive">"{@link direc
They apply special behavior to attributes or elements in the HTML. In the example above we use the
{@link ng.directive:ngApp `ng-app`} attribute, which is linked to a directive that automatically
initializes our application. Angular also defines a directive for the {@link ng.directive:input `input`}
element that adds extra behavior to the element. E.g. it is able to automatically validate that the entered
text is non empty by evaluating the `required` attribute.
The {@link ng.directive:ngModel `ng-model`} directive stores/updates
the value of the input field into/from a variable and shows the validation state of the input field by
adding css classes. In the example we use these css classes to mark an empty input field with a red border.
element that adds extra behavior to the element. The {@link ng.directive:ngModel `ng-model`} directive
stores/updates the value of the input field into/from a variable.
<div class="alert alert-info">
**Custom directives to access the DOM**: In Angular, the only place where an application touches the DOM is
@@ -131,10 +129,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" ng-model="invoice.qty" required >
Quantity: <input type="number" min="0" ng-model="invoice.qty" required >
</div>
<div>
Costs: <input type="number" ng-model="invoice.cost" required >
Costs: <input type="number" min="0" ng-model="invoice.cost" required >
<select ng-model="invoice.inCurr">
<option ng-repeat="c in invoice.currencies">{{c}}</option>
</select>
@@ -231,10 +229,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" ng-model="invoice.qty" required >
Quantity: <input type="number" min="0" ng-model="invoice.qty" required >
</div>
<div>
Costs: <input type="number" ng-model="invoice.cost" required >
Costs: <input type="number" min="0" ng-model="invoice.cost" required >
<select ng-model="invoice.inCurr">
<option ng-repeat="c in invoice.currencies">{{c}}</option>
</select>
@@ -323,7 +321,7 @@ The following example shows how this is done with Angular:
angular.module('finance3', [])
.factory('currencyConverter', ['$http', function($http) {
var YAHOO_FINANCE_URL_PATTERN =
'http://query.yahooapis.com/v1/public/yql?q=select * from '+
'//query.yahooapis.com/v1/public/yql?q=select * from '+
'yahoo.finance.xchange where pair in ("PAIRS")&format=json&'+
'env=store://datatables.org/alltableswithkeys&callback=JSON_CALLBACK';
var currencies = ['USD', 'EUR', 'CNY'];
@@ -359,10 +357,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" ng-model="invoice.qty" required >
Quantity: <input type="number" min="0" ng-model="invoice.qty" required >
</div>
<div>
Costs: <input type="number" ng-model="invoice.cost" required >
Costs: <input type="number" min="0" ng-model="invoice.cost" required >
<select ng-model="invoice.inCurr">
<option ng-repeat="c in invoice.currencies">{{c}}</option>
</select>
+20 -26
View File
@@ -1,5 +1,6 @@
@ngdoc overview
@name Controllers
@sortOrder 220
@description
# Understanding Controllers
@@ -37,27 +38,8 @@ The properties contain the **view model** (the model that will be presented by t
`$scope` properties will be available to the template at the point in the DOM where the Controller
is registered.
The following example shows a very simple constructor function for a Controller, `GreetingController`,
which attaches a `greeting` property containing the string `'Hola!'` to the `$scope`:
```js
function GreetingController($scope) {
$scope.greeting = 'Hola!';
}
```
Once the Controller has been attached to the DOM, the `greeting` property can be data-bound to the
template:
```js
<div ng-controller="GreetingController">
{{ greeting }}
</div>
```
**NOTE**: Although Angular allows you to create Controller functions in the global scope, this is
not recommended. In a real application you should use the `.controller` method of your
{@link module Angular Module} for your application as follows:
The following example demonstrates creating a `GreetingController`, which attaches a `greeting`
property containing the string `'Hola!'` to the `$scope`:
```js
var myApp = angular.module('myApp',[]);
@@ -67,9 +49,24 @@ myApp.controller('GreetingController', ['$scope', function($scope) {
}]);
```
We create an {@link module Angular Module}, `myApp`, for our application. Then we add the controller's
constructor function to the module using the `.controller()` method. This keeps the controller's
constructor function out of the global scope.
<div class="alert alert-info">
We have used an **inline injection annotation** to explicitly specify the dependency
of the Controller on the `$scope` service provided by Angular. See the guide on
[Dependency Injection](http://docs.angularjs.org/guide/di) for more information.
{@link guide/di Dependency Injection} for more information.
</div>
We attach our controller to the DOM using the `ng-controller` directive. The `greeting` property can
now be data-bound to the template:
```js
<div ng-controller="GreetingController">
{{ greeting }}
</div>
```
# Adding Behavior to a Scope Object
@@ -162,7 +159,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" or "Controller".
starts with capital letter and ends with "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
@@ -333,6 +330,3 @@ describe('state', function() {
});
});
```
+1
View File
@@ -1,5 +1,6 @@
@ngdoc overview
@name Working With CSS
@sortOrder 510
@description
+1
View File
@@ -1,5 +1,6 @@
@ngdoc overview
@name Data Binding
@sortOrder 210
@description
Data-binding in Angular apps is the automatic synchronization of data between the model and view
+20 -12
View File
@@ -1,5 +1,6 @@
@ngdoc overview
@name Dependency Injection
@sortOrder 250
@description
# Dependency Injection
@@ -109,7 +110,7 @@ asks the injector to create an instance of the controller and its dependencies.
injector.instantiate(MyController);
```
This is all done behinds the scenes. Notice that by having the `ng-controller` ask the injector to
This is all done behind the scenes. Notice that by having the `ng-controller` ask the injector to
instantiate the class, it can satisfy all of the dependencies of `MyController` without the
controller ever knowing about the injector.
@@ -135,7 +136,7 @@ These can be used interchangeably as you see fit and are equivalent.
### Implicit Dependencies
The simplest way to get hold of the dependencies, is to assume that the function parameter names
The simplest way to get hold of the dependencies is to assume that the function parameter names
are the names of the dependencies.
```js
@@ -144,7 +145,7 @@ function MyController($scope, greeter) {
}
```
Given a function the injector can infer the names of the service to inject by examining the
Given a function the injector can infer the names of the services to inject by examining the
function declaration and extracting the parameter names. In the above example `$scope`, and
`greeter` are two services which need to be injected into the function.
@@ -154,7 +155,7 @@ rename the method parameter names. This makes this way of annotating only useful
### `$inject` Property Annotation
To allow the minifiers to rename the function parameters and still be able to inject right services,
To allow the minifiers to rename the function parameters and still be able to inject the right services,
the function needs to be annotated with the `$inject` property. The `$inject` property is an array
of service names to inject.
@@ -166,7 +167,7 @@ MyController['$inject'] = ['$scope', 'greeter'];
```
In this scenario the ordering of the values in the `$inject` array must match the ordering of the
arguments to inject. Using above code snippet as an example, `$scope` will be injected into
arguments to inject. Using the above code snippet as an example, `$scope` will be injected into
`renamed$scope` and `greeter` into `renamedGreeter`. Care must be taken that the `$inject`
annotation is kept in sync with the actual arguments in the function declaration.
@@ -206,7 +207,7 @@ someModule.factory('greeter', ['$window', function(renamed$window) {
}]);
```
Here, instead of simply providing the factory function, we pass an array, whose elements consist of
Here, instead of simply providing the factory function, we pass an array whose elements consist of
a list of strings (the names of the dependencies) followed by the function itself.
Keep in mind that all of the annotation styles are equivalent and can be used anywhere in Angular
@@ -218,15 +219,22 @@ DI is pervasive throughout Angular. You can use it when defining components or w
and `config` blocks for a module.
- Components such as services, directives, filters and animations are defined by an injectable factory
method or constructor function. These components can be injected with "service" components as
dependencies.
- The `run` and `config` methods accept a function, which can also be injected with "service"
method or constructor function. These components can be injected with "service" and "value"
components as dependencies.
- The `run` method accepts a function, which can be injected with "service", "value" and "constant"
components as dependencies. Note that you cannot inject "providers" into `run` blocks.
- The `config` method accepts a function, which can be injected with "provider" and "constant"
components as dependencies. Note that you cannot inject "service" or "value" components into
configuration
- Controllers are defined by a constructor function, which can be injected with any of the "service"
components as dependencies, but they can also be provided with special dependencies. See "DI in
Controllers" below.
and "value" components as dependencies, but they can also be provided with special dependencies. See
{@link di#controllers Controllers} below for a list of these special dependencies.
See {@link module#module-loading-dependencies Modules} for more details about injecting dependencies
into `run` and `config` blocks.
### Factory Methods
+33 -7
View File
@@ -1,5 +1,6 @@
@ngdoc overview
@name Directives
@sortOrder 300
@description
# Creating Custom Directives
@@ -84,7 +85,7 @@ Here are some equivalent examples of elements that match `ngBind`:
<span x-ng-bind="name"></span> <br/>
</div>
</file>
<file name="protractorTest.js">
<file name="protractor.js" type="protractor">
it('should show off bindings', function() {
expect(element(by.css('div[ng-controller="Controller"] span[ng-bind]')).getText())
.toBe('Max Karl Ernst Ludwig Planck (April 23, 1858 October 4, 1947)');
@@ -161,7 +162,9 @@ With `ng-attr-cx` you can work around this problem.
If an attribute with a binding is prefixed with the `ngAttr` prefix (denormalized as `ng-attr-`)
then during the binding will be applied to the corresponding unprefixed attribute. This allows
you to bind to attributes that would otherwise be eagerly processed by browsers
(e.g. an SVG element's `circle[cx]` attributes).
(e.g. an SVG element's `circle[cx]` attributes). When using `ngAttr`, the `allOrNothing` flag of
{@link ng.$interpolate $interpolate} is used, so if any expression in the interpolated string
results in `undefined`, the attribute is removed and not added to the element.
For example, we could fix the example above by instead writing:
@@ -283,8 +286,8 @@ Great! But what if we wanted to have our directive match the tag name `<my-custo
If we simply put a `<my-customer>` element into the HTML, it doesn't work.
<div class="alert alert-warning">
**Note:** When you create a directive, it is restricted to attribute only by default. In order to
create directives that are triggered by element or class name, you need to use the `restrict` option.
**Note:** When you create a directive, it is restricted to attribute and elements only by default. In order to
create directives that are triggered by class name, you need to use the `restrict` option.
</div>
The `restrict` option is typically set to:
@@ -352,7 +355,7 @@ element as a customer component.
Our `myCustomer` directive above is great, but it has a fatal flaw. We can only use it once within a
given scope.
In its current implementation, we'd need to create a different controller each time In order to
In its current implementation, we'd need to create a different controller each time in order to
re-use such a directive:
<example module="docsScopeProblemExample">
@@ -475,7 +478,6 @@ within our directive's template:
angular.module('docsIsolationExample', [])
.controller('Controller', ['$scope', function($scope) {
$scope.naomi = { name: 'Naomi', address: '1600 Amphitheatre' };
$scope.vojta = { name: 'Vojta', address: '3456 Somewhere Else' };
}])
.directive('myCustomer', function() {
@@ -537,7 +539,7 @@ where:
In our `link` function, we want to update the displayed time once a second, or whenever a user
changes the time formatting string that our directive binds to. We will use the `$interval` service
to call a handler on a regular basis. This is easier than using `$timeout` but also works better with
end-to-end testing, where we want to ensure that all $timeouts have completed before completing the test.
end-to-end testing, where we want to ensure that all `$timeout`s have completed before completing the test.
We also want to remove the `$interval` if the directive is deleted so we don't introduce a memory leak.
<example module="docsTimeDirective">
@@ -910,6 +912,30 @@ Looking back at `myPane`'s definition, notice the last argument in its `link` fu
When a directive requires a controller, it receives that controller as the fourth argument of its
`link` function. Taking advantage of this, `myPane` can call the `addPane` function of `myTabs`.
If multiple controllers are required, the `require` option of the directive can take an array argument.
The corresponding parameter being sent to the `link` function will also be an array.
```js
angular.module('docsTabsExample', [])
.directive('myPane', function() {
return {
require: ['^myTabs', '^ngModel'],
restrict: 'E',
transclude: true,
scope: {
title: '@'
},
link: function(scope, element, attrs, controllers) {
var tabsCtrl = controllers[0],
modelCtrl = controllers[1];
tabsCtrl.addPane(scope);
},
templateUrl: 'my-pane.html'
};
});
```
Savvy readers may be wondering what the difference is between `link` and `controller`.
The basic difference is that `controller` can expose an API, and `link` functions can interact with
controllers using `require`.
+1 -1
View File
@@ -1,6 +1,6 @@
@workInProgress
@ngdoc overview
@name E2E Testing
@sortOrder 420
@description
# E2E Testing
+27 -22
View File
@@ -1,5 +1,6 @@
@ngdoc overview
@name Expressions
@sortOrder 270
@description
# Angular Expressions
@@ -38,7 +39,9 @@ the method from your view. If you want to `eval()` an Angular expression yoursel
## Example
<example>
<file name="index.html">
1+2={{1+2}}
<span>
1+2={{1+2}}
</span>
</file>
<file name="protractor.js" type="protractor">
@@ -50,9 +53,9 @@ the method from your view. If you want to `eval()` an Angular expression yoursel
You can try evaluating different expressions here:
<example>
<example module="expressionExample">
<file name="index.html">
<div ng-controller="Cntl2" class="expressions">
<div ng-controller="ExampleController" class="expressions">
Expression:
<input type='text' ng-model="expr" size="80"/>
<button ng-click="addExp(expr)">Evaluate</button>
@@ -66,23 +69,24 @@ You can try evaluating different expressions here:
</file>
<file name="script.js">
function Cntl2($scope) {
var exprs = $scope.exprs = [];
$scope.expr = '3*10|currency';
$scope.addExp = function(expr) {
exprs.push(expr);
};
angular.module('expressionExample', [])
.controller('ExampleController', ['$scope', function($scope) {
var exprs = $scope.exprs = [];
$scope.expr = '3*10|currency';
$scope.addExp = function(expr) {
exprs.push(expr);
};
$scope.removeExp = function(index) {
exprs.splice(index, 1);
};
}
$scope.removeExp = function(index) {
exprs.splice(index, 1);
};
}]);
</file>
<file name="protractor.js" type="protractor">
it('should allow user expression testing', function() {
element(by.css('.expressions button')).click();
var lis = element(by.css('.expressions ul')).element.all(by.repeater('expr in exprs'));
var lis = element(by.css('.expressions ul')).all(by.repeater('expr in exprs'));
expect(lis.count()).toBe(1);
expect(lis.get(0).getText()).toEqual('[ X ] 3*10|currency => $30.00');
});
@@ -101,9 +105,9 @@ This restriction is intentional. It prevents accidental access to the global sta
Instead use services like `$window` and `$location` in functions called from expressions. Such services
provide mockable access to globals.
<example>
<example module="expressionExample">
<file name="index.html">
<div class="example2" ng-controller="Cntl1">
<div class="example2" ng-controller="ExampleController">
Name: <input ng-model="name" type="text"/>
<button ng-click="greet()">Greet</button>
<button ng-click="window.alert('Should not see me')">Won't greet</button>
@@ -111,13 +115,14 @@ provide mockable access to globals.
</file>
<file name="script.js">
function Cntl1($window, $scope){
$scope.name = 'World';
angular.module('expressionExample', [])
.controller('ExampleController', ['$window', '$scope', function($window, $scope) {
$scope.name = 'World';
$scope.greet = function() {
$window.alert('Hello ' + $scope.name);
};
}
$scope.greet = function() {
$window.alert('Hello ' + $scope.name);
};
}]);
</file>
<file name="protractor.js" type="protractor">
+1
View File
@@ -1,5 +1,6 @@
@ngdoc overview
@name Filters
@sortOrder 280
@description
A filter formats the value of an expression for display to the user. They can be used in view templates,
+56 -50
View File
@@ -1,5 +1,6 @@
@ngdoc overview
@name Forms
@sortOrder 290
@description
Controls (`input`, `select`, `textarea`) are ways for a user to enter data.
@@ -16,9 +17,9 @@ The key directive in understanding two-way data-binding is {@link ng.directive:n
The `ngModel` directive provides the two-way data-binding by synchronizing the model to the view, as well as view to the model.
In addition it provides an {@link ngModel.NgModelController API} for other directives to augment its behavior.
<example>
<example module="formExample">
<file name="index.html">
<div ng-controller="Controller">
<div ng-controller="ExampleController">
<form novalidate class="simple-form">
Name: <input type="text" ng-model="user.name" /><br />
E-mail: <input type="email" ng-model="user.email" /><br />
@@ -32,19 +33,20 @@ In addition it provides an {@link ngModel.NgModelController API} for other direc
</div>
<script>
function Controller($scope) {
$scope.master = {};
angular.module('formExample', [])
.controller('ExampleController', ['$scope', function($scope) {
$scope.master = {};
$scope.update = function(user) {
$scope.master = angular.copy(user);
};
$scope.update = function(user) {
$scope.master = angular.copy(user);
};
$scope.reset = function() {
$scope.user = angular.copy($scope.master);
};
$scope.reset = function() {
$scope.user = angular.copy($scope.master);
};
$scope.reset();
}
$scope.reset();
}]);
</script>
</file>
</example>
@@ -69,9 +71,9 @@ The following example uses the CSS to display validity of each form control.
In the example both `user.name` and `user.email` are required, but are rendered with red background only when they are dirty.
This ensures that the user is not distracted with an error until after interacting with the control, and failing to satisfy its validity.
<example>
<example module="formExample">
<file name="index.html">
<div ng-controller="Controller">
<div ng-controller="ExampleController">
<form novalidate class="css-form">
Name:
<input type="text" ng-model="user.name" required /><br />
@@ -94,19 +96,20 @@ This ensures that the user is not distracted with an error until after interacti
</style>
<script>
function Controller($scope) {
$scope.master = {};
angular.module('formExample', [])
.controller('ExampleController', ['$scope', function($scope) {
$scope.master = {};
$scope.update = function(user) {
$scope.master = angular.copy(user);
};
$scope.update = function(user) {
$scope.master = angular.copy(user);
};
$scope.reset = function() {
$scope.user = angular.copy($scope.master);
};
$scope.reset = function() {
$scope.user = angular.copy($scope.master);
};
$scope.reset();
}
$scope.reset();
}]);
</script>
</file>
</example>
@@ -132,9 +135,9 @@ This allows us to extend the above example with these features:
- SAVE button is enabled only if form has some changes and is valid
- custom error messages for `user.email` and `user.agree`
<example>
<example module="formExample">
<file name="index.html">
<div ng-controller="Controller">
<div ng-controller="ExampleController">
<form name="form" class="css-form" novalidate>
Name:
<input type="text" ng-model="user.name" name="uName" required /><br />
@@ -161,23 +164,24 @@ This allows us to extend the above example with these features:
</file>
<file name="script.js">
function Controller($scope) {
$scope.master = {};
angular.module('formExample', [])
.controller('ExampleController', ['$scope', function($scope) {
$scope.master = {};
$scope.update = function(user) {
$scope.master = angular.copy(user);
};
$scope.update = function(user) {
$scope.master = angular.copy(user);
};
$scope.reset = function() {
$scope.user = angular.copy($scope.master);
};
$scope.reset = function() {
$scope.user = angular.copy($scope.master);
};
$scope.isUnchanged = function(user) {
return angular.equals(user, $scope.master);
};
$scope.isUnchanged = function(user) {
return angular.equals(user, $scope.master);
};
$scope.reset();
}
$scope.reset();
}]);
</file>
</example>
@@ -196,12 +200,12 @@ 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
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>
<example module="customTriggerExample">
<file name="index.html">
<div ng-controller="ControllerUpdateOn">
<div ng-controller="ExampleController">
<form>
Name:
<input type="text" ng-model="user.name" ng-model-options="{ updateOn: 'blur' }" /><br />
@@ -212,9 +216,10 @@ only when the control loses focus (blur event).
</div>
</file>
<file name="script.js">
function ControllerUpdateOn($scope) {
$scope.user = {};
}
angular.module('customTriggerExample', [])
.controller('ExampleController', ['$scope', function($scope) {
$scope.user = {};
}]);
</file>
</example>
@@ -240,9 +245,9 @@ overridden.
This example shows how to debounce model changes. Model will be updated only 250 milliseconds after last change.
<example>
<example module="debounceExample">
<file name="index.html">
<div ng-controller="ControllerUpdateOn">
<div ng-controller="ExampleController">
<form>
Name:
<input type="text" ng-model="user.name" ng-model-options="{ debounce: 250 }" /><br />
@@ -251,9 +256,10 @@ This example shows how to debounce model changes. Model will be updated only 250
</div>
</file>
<file name="script.js">
function ControllerUpdateOn($scope) {
$scope.user = {};
}
angular.module('debounceExample', [])
.controller('ExampleController', ['$scope', function($scope) {
$scope.user = {};
}]);
</file>
</example>
+2 -1
View File
@@ -1,5 +1,6 @@
@ngdoc overview
@name i18n and l10n
@sortOrder 520
@description
# i18n and l10n
@@ -114,7 +115,7 @@ You write the following binding using the currency filter:
If your app is currently in the `en-US` locale, the browser will show `$1000.00`. If someone in the
Japanese locale (`ja`) views your app, their browser will show a balance of `¥1000.00` instead.
This is problematinc because $1000 is not the same as ¥1000.
This is problematic because $1000 is not the same as ¥1000.
In this case, you need to override the default currency symbol by providing the
{@link ng.filter:currency} currency filter with a currency symbol as a parameter.
+1
View File
@@ -1,5 +1,6 @@
@ngdoc overview
@name Internet Explorer Compatibility
@sortOrder 530
@description
# Internet Explorer Compatibility
+3 -2
View File
@@ -47,7 +47,7 @@ In Angular applications, you move the job of filling page templates with data fr
### Testing
* **Unit testing:** [Using Karma (video)](http://www.youtube.com/watch?v=YG5DEzaQBIc), {@link guide/dev_guide.unit-testing Unit testing}, {@link guide/dev_guide.services.testing_services Testing services}, [Karma in Webstorm](http://blog.jetbrains.com/webstorm/2013/10/running-javascript-tests-with-karma-in-webstorm-7/)
* **Unit testing:** [Using Karma (video)](http://www.youtube.com/watch?v=YG5DEzaQBIc), {@link guide/unit-testing Unit testing}, {@link guide/services#unit-testing Testing services}, [Karma in Webstorm](http://blog.jetbrains.com/webstorm/2013/10/running-javascript-tests-with-karma-in-webstorm-7/)
* **Scenario testing:** [Protractor](https://github.com/angular/protractor)
## Specific Topics
@@ -81,7 +81,8 @@ 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/), [ngmin automation tool](http://www.thinkster.io/pick/XlWneEZCqY/angularjs-ngmin)
* **Docs Page:** {@link guide/production Running an AngularJS App in Production}
* **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)
* **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/)

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