Commit Graph

1648 Commits

Author SHA1 Message Date
Matias Niemelä
708f2ba984 fix($animate): ensure class-based animations always perform a domOperation if skipped
Closes #6957
2014-04-04 11:39:08 -04:00
Luis Ramón López
dbe381f29f feat(ngModelOptions): custom triggers and debounce of ngModel updates
By default, any change to an input will trigger an immediate model update,
form validation and run a $digest. This is not always desirable, especially
when you have a large number of bindings to update.

This PR implements a new directive `ngModelOptions`, which allow you to
override this default behavior in several ways. It is implemented as an
attribute, to which you pass an Angular expression, which evaluates to an
**options** object.

All inputs, using ngModel, will search for this directive in their ancestors
and use it if found.  This makes it easy to provide options for a whole
form or even the whole page, as well as specifying exceptions for
individual inputs.

* You can specify what events trigger an update to the model by providing
  an `updateOn` property on the **options** object. This property takes a
  string containing a space separated list of events.

  For example, `ng-model-options="{ updateOn: 'blur' }"` will update the
  model only after the input loses focus.

  There is a special pseudo-event, called "default", which maps to the
  default event used by the input box normally. This is useful if you
  want to keep the default behavior and just add new events.

* You can specify a debounce delay, how long to wait after the last triggering
  event before updating the model, by providing a `debounce` property on
  the **options** object.

  This property can be a simple number, the
  debounce delay for all events. For example,
  `ng-model-options="{ debounce: 500 }" will ensure the model is updated
  only when there has been a period 500ms since the last triggering event.

  The property can also be an object, where the keys map to events and
  the values are a corresponding debounce delay for that event.
  This can be useful to force immediate updates on some specific
  circumstances (like blur events). For example,
  `ng-model-options="{ updateOn: 'default blur', debounce: { default: 500, blur: 0} }"`

This commit also brings to an end one of the longest running Pull Requests
in the history of AngularJS (#2129)!  A testament to the patience of @lrlopez.

Closes #1285, #2129, #6945
2014-04-04 14:48:53 +01:00
Matias Niemelä
1cb8584e84 fix($animate): insert elements at the start of the parent container instead of at the end
With 1.2.x, `$animate.enter` and `$animate.move` both insert the element at the end of the provided
parent container element when only the `parent` element is provided. If an `after` element is provided
then they will place the inserted element after that one. This works fine, but there is no way to
place an item at the top of the provided parent container using these two APIs.

With this change, if the `after` argument is not specified for either `$animate.enter` or `$animate.move`,
the new child element will be inserted into the first position of the parent container element.

Closes #4934
Closes #6275

BREAKING CHANGE: $animate will no longer default the after parameter to the last element of the parent
container. Instead, when after is not specified, the new element will be inserted as the first child of
the parent container.

To update existing code, change all instances of `$animate.enter()` or `$animate.move()` from:

`$animate.enter(element, parent);`

to:

`$animate.enter(element, parent, angular.element(parent[0].lastChild));`
2014-04-03 17:07:43 -04:00
Matias Niemelä
c67bd69c58 fix($animate): ensure the CSS driver properly works with SVG elements
The default CSS driver in ngAnimate directly uses node.className when reading
the CSS class string on the given element. While this works fine with standard
HTML DOM elements, SVG elements have their own DOM property. By switching to use
node.getAttribute, ngAnimate can extract the element's className value without
throwing an exception.

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

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

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

Closes #5271
2014-04-03 11:55:54 -07:00
Igor Minar
d64d41ed99 fix(Scope): more scope clean up on $destroy to minimize leaks
Due to a known V8 memory leak[1] we need to perform extra cleanup to make it easier
for GC to collect this scope object.

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

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

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

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

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

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

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

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

Closes #6794
Closes #6856
Closes #6968
2014-04-03 00:25:01 -07:00
Igor Minar
f9eb324716 chore(rootScopeSpec): fix a typo in spec description 2014-04-02 21:24:40 -07:00
Alexander Harding
2e3a972b32 test($compile): add tests for <option> or <optgroup> tags as root template nodes 2014-04-02 19:40:16 -04:00
Caitlin Potter
ddb8081982 refactor(jqLite): make HTML-parsing constructor more robust
Previously, the jqLite constructor was limited and would be unable to circumvent many of the HTML5
spec's "allowed content" policies for various nodes. This led to complicated and gross hacks around
this in the HTML compiler.

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

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

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

Closes #6932
2014-04-02 10:05:45 -04:00
Matias Niemelä
908ab52b8d chore($animate): fix broken IE8 test 2014-03-28 14:13:35 -04:00
Matias Niemelä
ff5cf736e5 fix($animate): prevent cancellation timestamp from being too far in the future
Closes #6748
2014-03-28 12:25:50 -04:00
jim lyndon
1d2414ca93 feat($http): add xhr statusText to completeRequest callback
Makes xhr status text accessible is $http success/error callback.
See www.w3.org/TR/XMLHttpRequest/#dom-xmlhttprequest-statustext

Closes #2335
Closes #2665
Closes #6713
2014-03-27 17:08:23 -04:00
Matias Niemelä
1bebe36aa9 fix($animate): make CSS blocking optional for class-based animations
$animate attempts places a `transition: none 0s` block on the element when
the first CSS class is applied if a transition animation is underway. This
works fine for structural animations (enter, leave and move), however, for
class-based animations, this poses a big problem. As of this patch, instead
of $animate placing the block, it is now the responsibility of the user to
place `transition: 0s none` into their class-based transition setup CSS class.
This way the animation will avoid all snapping and any will allow $animate to
play nicely with class-based transitions that are defined outside of ngAnimate.

Closes #6674
Closes #6739

BREAKING CHANGE: Any class-based animation code that makes use of transitions
and uses the setup CSS classes (such as class-add and class-remove) must now
provide a empty transition value to ensure that its styling is applied right
away. In other words if your animation code is expecting any styling to be
applied that is defined in the setup class then it will not be applied
"instantly" default unless a `transition:0s none` value is present in the styling
for that CSS class. This situation is only the case if a transition is already
present on the base CSS class once the animation kicks off.
2014-03-26 12:48:53 -04:00
Matias Niemelä
2317af6851 fix($animate): run CSS animations before JS animations to avoid style inheritance
If a JS animation is run before a CSS animation then the JS animation may end up writing style
data to the element. If any transition or animation style data is written then it may end up
being accidentally inherited into the CSS animation hanlder that ngAnimate uses. This may result
in an unexpected outcome due to the tweaks and hacks that the CSS handler places on the element.
If the CSS animation is run before the JS animation then, if there are no transitions on the style
attribute nor within the global CSS on the page then nothing will happen and the JS animation can
work as expected.

Closes #6675
2014-03-26 12:11:25 -04:00
Caitlin Potter
6011145cfe test($rootScope): add assertion to test ensuring that NaN -> NaN does not throw
fb6062fb9d implements a
fix for NaN values causing $watchCollection to throw an infdig error. This change updates the test
by adding an assertion which explains what is actually being tested a bit better, and may also
provide better information in the event that the test ever fails.

Closes #6758
2014-03-20 17:53:03 -04:00
Sekib Omazic
fb6062fb9d fix($rootScope): ng-repeat can't handle NaN values. #4605
$watchCollection checks if oldValue !== newValue which does not work for NaN. This was causing
infinite digest errors, since comparing NaN to NaN in $watchCollection would always return false,
indicating that a change was occuring on each loop.

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

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

Closes #5017
Closes #6730
2014-03-18 21:30:29 -07:00
Jeff Balboni
f40f54c6da fix(select): avoid checking option element selected properties in render
In Firefox, hovering over an option in an open select menu updates the selected property of option
elements. This means that when a render is triggered by the digest cycle, and the list of options
is being rendered, the selected properties are reset to the values from the model and the option
hovered over changes. This fix changes the code to only use DOM elements' selected properties in a
comparison when a change event has been fired. Otherwise, the internal new and existing option
arrays are used.

Closes #2448
Closes #5994
2014-03-18 23:18:42 -04:00
Caitlin Potter
37bc5ef4d8 fix(orderBy): support string predicates containing non-ident characters
The orderBy filter now allows string predicates passed to the orderBy filter to make use property
name predicates containing non-ident strings, such as spaces or percent signs, or non-latin
characters.

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

In markup, this might look like so:

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

Or in JS:

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

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

Closes #6151
Closes #6220
2014-03-18 22:50:17 -04:00
Chris Constantin
bc42950b51 fix(ngTouch): update workaround for desktop Webkit quirk
Fix click busting of input click triggered by a label click quickly
following a touch event on a different element, in desktop
and mobile WebKit

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

Closes #6302
2014-03-18 22:30:23 -04:00
Caitlin Potter
6680b7b97c fix($httpBackend): don't error when JSONP callback called with no parameter
This change brings Angular's JSONP behaviour closer in line with jQuery's. It will no longer treat
a callback called with no data as an error, and will no longer support IE8 via the onreadystatechanged
event.

BREAKING CHANGE:

Previously, the JSONP backend code would support IE8 by relying on the readystatechanged events. This
is no longer the case, as these events do not provide adequate useful information for deeming whether
or not a response is an error.

Previously, a JSONP response which did not pass data into the callback would be given a status of -2,
and treated as an error. Now, this situation will instead be given a status of 200, despite the lack
of data. This is useful for interaction with certain APIs.

Previously, the onload and onerror callbacks were added to the JSONP script tag. These have been
replaced with jQuery events, in order to gain access to the event object. This means that it is now
difficult to test if the callbacks are registered or not. This is possible with jQuery, using the
$.data("events") method, however it is currently impossible with jqLite. This is not expected to
break applications.

Closes #4987
Closes #6735
2014-03-18 21:49:35 -04:00
Traxmaxx
c839f78b8f fix($$RAFProvider): check for webkitCancelRequestAnimationFrame
Android 4.3 only supports webkitCancelRequestAnimationFrame.

Closes #6526
2014-03-18 21:37:04 -04:00
Caio Cunha
d6cfcacee1 feat(ngMock.$httpBackend): added support for function as URL matcher
It's now possible to pass a function to match the URL in $httpBackend mocked
expectations. This gives a more sophisticate control over the URL matching
without requiring complex RegExp mantainance or the workaround of creating
an object with a `test` function in order to mimic RegExp interface.

This approach was suggested in [this
thread](https://groups.google.com/d/msg/angular/3QsCUEvvxlM/Q4C4ZIqNIuEJ)

Closes #4580
2014-03-18 15:19:26 -07:00
Caio Cunha
299b220f5e feat($compile): add support for $observer deregistration
In order to make the behavior compatible with $rootScope.$watch and $rootScope.$on methods, and
make it possible to deregister an attribute observer, Attributes.$observe method now returns a
deregistration function instead of the observer itself.

BREAKING CHANGE: calling attr.$observe no longer returns the observer function, but a
    deregistration function instead.

    To migrate the code follow the example below:

    Before:

```
    directive('directiveName', function() {
      return {
        link: function(scope, elm, attr) {
          var observer = attr.$observe('someAttr', function(value) {
            console.log(value);
          });
        }
      };
    });
```

    After:

```
    directive('directiveName', function() {
      return {
        link: function(scope, elm, attr) {
          var observer = function(value) {
            console.log(value);
          };

          attr.$observe('someAttr', observer);
        }
      };
    });
```

Closes #5609
2014-03-18 13:44:16 -07:00
Igor Minar
78057a945e fix(Scope): $watchCollection should call listener with oldValue
Originally we destroyed the oldValue by incrementaly copying over portions of the newValue
into the oldValue during dirty-checking, this resulted in oldValue to be equal to newValue
by the time we called the watchCollection listener.

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

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

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

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

instead of:

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

do:

```
// do work
expect(log.empty()).toEqual(['bar']);
```
2014-03-18 12:00:50 -07:00
Caitlin Potter
8a96f317e5 fix(jqLite): traverse host property for DocumentFragment in inheritedData()
If dealing with a document fragment node with a host element, and no parent, use the host
element as the parent. This enables directives within a Shadow DOM or polyfilled Shadow DOM
to lookup parent controllers.

Closes #6637
2014-03-17 16:52:48 -04:00
Bruno Baia
b8cc71d476 fix($http): allow sending Blob data using $http
Closes #5012
2014-03-15 19:41:07 +01:00
Pawel Kozlowski
56e73ea355 fix($http): don't covert 0 status codes to 404 for non-file protocols
PR #5547 introduced conversion of all 0 status codes to 404 for cases
where no response was recieved (previously this was done for the
file:// protocol only). But this mechanism is too eager and
masks legitimate cases where status 0 should be returned. This commits
reverts to the previous mechanism of handling 0 status code for the
file:// protocol (converting 0 to 404) while retaining the returned
status code 0 for all the protocols other than file://

Fixes #6074
Fixes #6155
2014-03-14 13:44:56 -07:00
Matias Niemelä
7b5e019981 fix($$rAF): always fallback to a $timeout incase native rAF isn't supported
Closes #6654
2014-03-14 12:42:07 -04:00
Tomer Chachamu
129e2e021a fix(ngAnimate): setting classNameFilter disables animation inside ng-if
Closes #6539
2014-03-14 12:40:40 -04:00
Igor Minar
47ab8df455 feat(): whitelist blob urls for sanitization of data-bound image urls
Closes #4623
2014-03-10 01:39:15 -07:00
Lucas Galfasó
53ec5e13e5 fix($compile): support templates with thead and tfoot root elements
If the first element in a template is a <thead> or a <tfoot>, then
use the existing logic to handle table elements compilation.

Closes #6289
2014-03-07 10:06:12 -08:00
Ben Lesh
46bd6dc88d feat(input): support types date, time, datetime-local, month, week
On older browser that don't support the new HTML5 inputs
and display a text input instead, the user is required to enter
the data in the corresponding ISO format. The value in `ng-model`
will always be a date.

E2e tests contain a workaround to a bug in webdriver,
see https://github.com/angular/protractor/issues/562.

Also adds weeks as format to the `dateFilter`.

Related to #757.
Closes #5864.
2014-03-06 12:21:15 -08:00
Sekib Omazic
0609453e1f fix(style): expressions in style tags
Enable data-binding for style tags.

Note: this feature does not work on IE8.

Closes #2387
Closes #6492
2014-03-06 02:19:30 -08:00
Timothée Jeannin
9335378602 style: enable jscs requireLeftStickedOperators rule
Closed #6544.
2014-03-05 16:30:51 -08:00
Matias Niemelä
18c41af065 fix($animate): delegate down to addClass/removeClass if setClass is not found
Closes #6463
2014-02-28 01:34:57 -05:00
Yves Brissaud
33443966c8 feat($animate): animate dirty, pristine, valid, invalid for form/fields
Add css animations when form or field status change to/from dirty,
pristine, valid or invalid. This works like animation system present
with ngClass, ngShow, etc.

Closes #5378
2014-02-28 01:01:34 -05:00
Pawel Kozlowski
4e73c80b17 fix(jqLite): properly toggle multiple classes
Fixes #4467
Closes #6448
2014-02-27 19:44:57 +01:00
Lajos Veres
27873acbf0 chore(qSpec): fix typos 2014-02-27 01:54:06 -08:00
Lajos Veres
4f48898728 chore(parseSpec): fix typo 2014-02-27 01:53:35 -08:00
Lajos Veres
0df6e20e6a chore(httpSpec): fix typo 2014-02-27 01:53:13 -08:00
Lajos Veres
074ad03072 chore(filtersSpec): fix typo 2014-02-27 01:52:51 -08:00
Lajos Veres
a20e76ea80 chore(ngRepeatSpec): fix typo 2014-02-27 01:52:21 -08:00
Lajos Veres
d59678a080 chore(AngularSpec): fix typo 2014-02-27 01:51:45 -08:00
Matias Niemelä
f4f1f43d51 fix($animate): ensure all comment nodes are removed during a leave animation
Closes #6403
2014-02-26 17:17:41 -05:00
Matias Niemelä
e71e7b6cae fix($animate): only block keyframes if a stagger is set to occur
Transitions must be blocked so that the initial CSS class can be applied
without triggering an animation. Keyframes do not need to be blocked since
animations are always triggered on the starting CSS class, however, if a
stagger animation is set to occur then all elements for index > 0 should
be blocked. This is to prevent the animation from occuring early on before
the stagger delay for the given element has passed.

With ngAnimate and keyframe animations, IE10 and Safari will render a slight
flicker effect caused by the blocking. This fix resolves this issue.

Closes #4225
2014-02-26 17:08:51 -05:00