Commit Graph

131 Commits

Author SHA1 Message Date
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
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
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
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
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
Igor Minar
8c6a8171f9 perf(Scope): change Scope#id to be a simple number
In apps that create lots of scopes (apps with large tables) the uid generation
shows up in the profiler and adds a few milliseconds. Using simple counter
doesn't have this overhead.

I think the initial fear of overflowing and thus using string alphanum sequence
is unjustified because even if an app was to create lots of scopes non-stop,
you could create about 28.6 million scopes per seconds for 10 years before
you would reach a number that can't be accurately represented in JS

BREAKING CHANGE: Scope#$id is now of time number rather than string. Since the
id is primarily being used for debugging purposes this change should not affect
anyone.
2014-06-13 11:35:26 -07:00
Peter Bacon Darwin
398053c563 fix($compile): ensure transclude works at root of templateUrl
If a "replace" directive has an async template, which contains a transclusion
directive at its root node, then outer transclusions were failing to be
passed to this directive.  An example would be uses of `ngIf` inside and
outside the template.

Collaborated with @caitp

Closes #7183
Closes #7772
2014-06-13 14:28:47 +01:00
Buu Nguyen
2cde927e58 fix($compile): always error if two directives add isolate-scope and new-scope
Previously, the compiler would throw an error if a directive requested new non-isolate scope
after a directive had requested isolate scope. But it would not error if a directive
requested an isolate scope after a directive had requested a new non-isolate scope.

Since it is invalid to have more than one directive request any kind of scope if one of
them has requested isolate scope, then the compiler should error whatever order the
directives are applied.

This fix addresses this situation by throwing error regardless of order of directives.

BREAKING CHANGE:

Requesting isolate scope and any other scope on a single element is an error.
Before this change, the compiler let two directives request a child scope
and an isolate scope if the compiler applied them in the order of non-isolate
scope directive followed by isolate scope directive.

Now the compiler will error regardless of the order.

If you find that your code is now throwing a `$compile:multidir` error,
check that you do not have directives on the same element that are trying
to request both an isolate and a non-isolate scope and fix your code.

Closes #4402
Closes #4421
2014-06-10 12:08:55 +01:00
rodyhaddad
c97c5cec2f test(jqLite): adapt missed test to new expando name 2014-06-05 14:45:26 -07:00
cexbrayat
24c844df3b fix($parse): fix parsing error with leading space and one time bind
Closes #7640
2014-06-02 13:23:21 -07:00
Phil Westwell
0dc35efd7c docs(*): fix its/it's grammar
Closes #7580
2014-05-31 18:43:26 -04:00
Vojta Jina
440be33d48 test($compile): transcludeFn is available in compile of templateUrl directive 2014-05-29 12:54:44 -07:00
Peter Bacon Darwin
2ee29c5da8 fix($compile): don't pass transcludes to non-transclude templateUrl directives 2014-05-29 12:52:12 -07:00
Peter Bacon Darwin
19af039745 fix($compile): don't pass transclude to template of non-transclude directive
If a directive provides a template but is not explicitly requesting transclusion
then the compiler should not pass a transclusion function to the directives
within the template.
2014-05-29 12:52:12 -07:00
Peter Bacon Darwin
d414b78717 fix($compile): fix nested isolated transclude directives
Closes #1809
Closes #7499
2014-05-29 12:52:11 -07:00
Peter Bacon Darwin
1fef5fe823 fix($compile): pass transcludeFn down to nested transclude directives
If you have two directives that both expect to receive transcluded content
the outer directive works but the inner directive never receives a
transclusion function. This only failed if the first transclude directive
was not the first directive found in compilation.

Handles the regression identified in e994259739

Fixes #7240
Closes #7387
2014-05-29 12:52:11 -07:00
Peter Bacon Darwin
bea77e4b15 style($compileSpec): fix typos 2014-05-29 12:52:11 -07:00
Lucas Galfaso
cee429f0aa feat(*): lazy one-time binding support
Expressions that start with `::` will be binded once. The rule
that binding follows is that the binding will take the first
not-undefined value at the end of a $digest cycle.

Watchers from $watch, $watchCollection and $watchGroup will
automatically stop watching when the expression(s) are bind-once
and fulfill.

Watchers from text and attributes interpolations will
automatically stop watching when the expressions are fulfill.

All directives that use $parse for expressions will automatically
work with bind-once expressions. E.g.

<div ng-bind="::foo"></div>
<li ng-repeat="item in ::items">{{::item.name}};</li>

Paired with: Caitlin and Igor
Design doc: https://docs.google.com/document/d/1fTqaaQYD2QE1rz-OywvRKFSpZirbWUPsnfaZaMq8fWI/edit#
Closes #7486
Closes #5408
2014-05-23 14:40:51 -07:00
Jeff Whelpley
1ab6e908b1 fix($compile): do not merge attrs that are the same for replace directives
If a directives specifies `replace:true` and the template of the directive contains
a root element with an attribute which already exists at the place
where the directive is used with the same value, don't duplicate the value.

Closes #7463
2014-05-21 15:51:19 -07:00
Igor Minar
e994259739 revert: fix($compile): pass transcludeFn down to nested transclude directives
This reverts commit 113850602d.

This change introduced regressions for several scenarios.

reduction: http://jsfiddle.net/5242N/4/
2014-05-20 11:00:26 -07:00
Brian Ford
96fa70511d test($compile): use trim helper 2014-05-16 18:18:26 -07:00
Vojta Jina
4f03dc5a96 fix($compile): pass transcludeFn down to nested transclude directives
If you have two directives that both expect to receive transcluded content
the outer directive works but the inner directive never receives a
transclusion function. This only failed if the first transclude directive
was not the first directive found in compilation.

Fixes #7240
Closes #7387
2014-05-16 13:08:10 -07:00
Shahar Talmi
562c4e424b fix($compile): set $isolateScope correctly for sync template directives
All isolated scope directives that do not have `templateUrl` were marked
as `$isolateScopeNoTemplate` even if they did have a `template` attribute.

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

Closes #6942
2014-05-09 14:42:26 +01:00
Caitlin Potter
f0e12ea7fe feat($compile): allow SVG and MathML templates via special type property
Previously, templates would always be assumed to be valid HTML nodes. In some cases, it is
desirable to use SVG or MathML or some other language.

For the time being, this change is only truly meaningful for SVG elements, as MathML has
very limited browser support. But in the future, who knows?

Closes #7265
2014-04-29 14:48:50 -04:00
Shahar Talmi
accd35b747 chore(jshint): enforce jshint for tests
Closes #7264
2014-04-27 21:20:31 +01:00
Igor Minar
1db3b8cfb7 refactor($interpolate): attempt to remove hacky code due to $interpolation perf improvements 2014-04-21 11:47:23 -07:00
Caitlin Potter
1192531e9b fix($compile): reference correct directive name in ctreq error
Previously, ctreq would possibly reference the incorrect directive name,
due to relying on a directiveName living outside of the closure which
throws the exception, which can change before the call is ever made.

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

Closes #7062
Closes #7067
2014-04-15 17:16:59 -04: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
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
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
Matias Niemelä
4f84f6b3e4 fix($animate): ensure $animate doesn't break natural CSS transitions
BREAKING CHANGE: ngClass and {{ class }} will now call the `setClass`
animation callback instead of addClass / removeClass when both a
addClass/removeClass operation is being executed on the element during the animation.

Please include the setClass animation callback as well as addClass and removeClass within
your JS animations to work with ngClass and {{ class }} directives.

Closes #6019
2014-02-14 16:30:48 -08:00
Caitlin Potter
31c450bcee fix($compile) support templates with table content root nodes
If the first element in a template is a <tr>, <th>, <td>, or <tbody> tag,
the HTML compiler will ensure that the template is wrapped in a <table>
element so that the table content is not discarded.

Closes #2848
Closes #1459
Closes #3647
Closes #3241
2014-02-14 14:42:55 -05:00
Caitlin Potter
e7338d3f27 fix($compile): ensure element transclusion directives are linked with comment element
This corrects a complicated compiler issue, described in detail below:

Previously, if an element transclusion directive contained an asynchronous directive whose template
contained another element transclusion directive, the inner element transclusion directive would be
linked with the element, rather than the expected comment node.

An example manifestation of this bug would look like so:

```html
<div ng-repeat="i in [1,2,3,4,5]">
  <div my-directive>
  </div>
</div>
```

`my-directive` would be a replace directive, and its template would contain another element
transclusion directive, like so:

```html
<div ng-if="true">{{i}}</div>
```

ngIf would be linked with this template content, rather than the comment node, and the template element
would be attached to the DOM, rather than the comment. As a result, this caused ng-if to duplicate the
template when its expression evaluated to true.

Closes #6006
Closes #6101
2014-02-10 18:41:28 -05:00
Matias Niemelä
4224cd5182 fix(mocks): rename mock.animate to ngAnimateMock and ensure it contains all test helper code for ngAnimate
Closes #5822
Closes #5917
2014-02-06 01:22:14 -05:00
Matias Niemelä
906fdad0f9 fix(mocks): remove usage of $animate.flushNext in favour of queing
The flushNext method of testing is difficult and highly coupled with the behavior
of ngAnimate's $animate workflow. It is much better instead to just queue all
$animate animation calls into a queue collection which is available on the $animate
service when mock.animate is included as a module within test code.
2014-02-06 01:21:41 -05:00
Caitlin Potter
5ed721b9b5 fix($compile): retain CSS classes added in cloneAttachFn on asynchronous directives
Previously, classes added to asynchronous directive elements during the clone
attach function would not persist after the node is merged with the template, prior
to linking. This change corrects this behaviour and brings it in line with synchronous
directives.

Closes #5439
Closes #5617
2014-01-31 12:45:35 -05:00
Igor Minar
e415e916e8 test(compileSpec): fix broken build on FF
FF 26.0 now throws:

"TypeError: NodeList doesn't have an indexed property setter."

when we try to assign to `childNodes[1]`, since this test still works properly
on Chrome and the issue being tested is not a cross-browser issues, I'm
just making the patchability check more robust instead of trying to figure
out how to make this test fully pass on FF.
2013-12-31 01:39:19 -08:00
Alexandre Potvin Latreille
c7a1d1ab0b fix($compile): remove invalid IE exceptional case for href
It appears that this exceptional case was only valid for IE<8 and that for IE>=8 it
was actually causing a bug with the `ng-href-attr` directive on `<a>` elements.

Closes #5479
2013-12-19 12:22:58 +00:00
Michał Gołębiowski
3410f65e79 perf(jqLite): implement and use the empty method in place of html(‘’)
jQuery's elem.html('') is way slower than elem.empty(). As clearing
element contents happens quite often in certain scenarios, switching
to using .empty() provides a significant performance boost when using
Angular with jQuery.

Closes #4457
2013-12-13 02:07:11 -08:00
Tobias Bosch
43072e3812 fix($compile): Allow literals in isolate scope references
When a component uses an isolate scope reference
and the the component is used with an object literal
a new object is created on every evaluation.
Therefore the compiler needs to compare
the values of the parent and the isolate scope
using object equality and not object reference
equality.

Fixes #5296.
2013-12-12 16:30:31 -08:00
Tobias Bosch
b0972a2e75 fix($compile): update cloned elements if the template arrives after the cloning
If an element has a directive whose content is loaded using `templateUrl`,
and the element is cloned using a linking function before the template arrives,
the clone needs to be updated as well.

This also updates `ngIf` and `ngRepeat` to keep the connection to the clone
of a tranclude function, so that they know about the changes a directive with
`templateUrl` does to the element in the future.

Fixes to #4930.
2013-12-05 22:16:25 -08:00
Daniel Tabuenca
2d0f6ccba8 fix($compile): ensure isolated local watches' lastValue is always in sync
When using two-way binding with isolate scope, under some circumstances
the lastValue variable captured in the parentValueWatch function can get
out of sync.

Specifically, if both the value in the origin scope as well as the value
in the isolate scope get independently updated to the same value within
one digest cycle, the lastValue is never updated. This potentially causes
the watch to make the wrong decision as to which side to update on subsequent
passes.

This fixes things by ensuring lastValue is always set to the last seen
value even if the watch's logic was short circuited because there was no
difference between the values in the original and isolate scopes.

Closes #5182
2013-12-04 09:45:20 -08:00
Tobias Bosch
333523483f fix($sanitize): Use same whitelist mechanism as $compile does.
`$sanitize` now uses the same mechanism as `$compile` to validate uris.
By this, the validation in `$sanitize` is more general and can be
configured in the same way as the one in `$compile`.

Changes
- Creates the new private service `$$sanitizeUri`.
- Moves related specs from `compileSpec.js` into `sanitizeUriSpec.js`.
- Refactors the `linky` filter to be less dependent on `$sanitize`
  internal functions.

Fixes #3748.
2013-11-26 14:29:38 -08:00
Igor Minar
84c408ce63 test($compile): correct the assertion to make test pass on IE11 2013-11-22 00:52:57 -08:00
Chirayu Krishnappa
0421cb4200 fix($compile): secure form[action] & iframe[srcdoc]
Require bindings to form[action] to be $sce.RESOURCE_URL and bindings to
iframe[srcdoc] to be $sce.HTML

Closes #4927
Closes #4933
2013-11-21 23:15:15 -08:00
Tobias Bosch
579242346c fix(tests): Correct tests for IE11
Some tests were wrong. However, src/* did not contain problems.

Fixes #5046
2013-11-21 21:53:09 -08:00
Matias Niemelä
0cd7e8f227 fix($compile): ensure CSS classes are added and removed only when necessary
When $compile interpolates a CSS class attribute expression it will
do so by comparing the CSS class value already present on the element.
This may lead to unexpected results when dealing with ngClass values being
added and removed therefore it is best that both compile and ngClass delegate
addClass/removeClass operations to the same block of code.
2013-11-21 20:47:44 -05:00
Tobias Bosch
90f87072e8 fix($compile): accessing controllers of transcluded directives from children
Additional API (backwards compatible)
- Injects `$transclude` (see directive controllers) as 5th argument to directive link functions.
- `$transclude` takes an optional scope as first parameter that overrides the
  bound scope.

Deprecations:
- `transclude` parameter of directive compile functions (use the new parameter for link functions instead).

Refactorings:
- Don't use comment node to temporarily store controllers
- `ngIf`, `ngRepeat`, ... now all use `$transclude`

Closes #4935.
2013-11-14 20:59:50 -08:00