Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also .

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also .
base repository: angular/angular.js
Choose a Base Repository
angular/angular.js
Anuj16/angular.js
ArslanRafique/angular.js
DeborahK/angular.js
EpokK/angular.js
HaoWu/angular.js
IgorMinar/angular.js
JKLFA/angular.js
KAUG/angular.js
Kaic-zz/angular.js
Metric7/angular.js
MikhailTatsky/angular.js
NAzT/angular.js
Narretz/angular.js
Partoo/angular.js
PeterBoesenberg/angular.js
PoshHsu/angular.js
ScxFiction/angular.js
SeanMBe/angular.js
Sharique-Hasan/angular.js
Shipow/angular.js
SjB/angular.js
Sophrinix/angular.js
SumitMunot/angular.js
TEHEK/angular.js
abhisec/angular.js
abnerlinan/angular.js
abrons/angular.js
acosme/angular.js
adam-singer/angular.js
addyosmani/angular.js
agborkowski/angular.js
ajperrins/angular.js
alexeagle/angular.js
alxross/angular.js
aminerahmouni/angular.js
amirhhz/angular.js
angeliaz/angular.js
angularjs-jp/angular.js
anjo/angular.js
arantius/angular.js
ardnet2/angular.js
arsh-co/angular.js
bartes/angular.js
bghanchi/angular.js
blinkbox/angular.js
blueslue/angular.js
boltz/angular.js
bolu/angular.js
briceburg/angular.js
brikou/angular.js
btford/angular.js
byplayer/angular.js
ca136/angular.js
calvinhuang/angular.js
cburgdorf/angular.js
chenermeng/angular.js
chris4403/angular.js
cleyshan/angular.js
codeinpeace/angular.js
colinfrei/angular.js
congmo/angular.js
crossbreeze/angular.js
csii/angular.js
cssgist/angular.js
danielfacanha/angular.js
danilopesouza/angular.js
dankrz/angular.js
dashersw/angular.js
dbinit/angular.js
dcu/angular.js
dhl/angular.js
dineshkummarc/angular.js
dolfly/angular.js
dydycloud/angular.js
eburley/angular.js
elfgoh/angular.js
esprehn/angular.js
fergaldoyle/angular.js
fingerskier/angular.js
flamilton/angular.js
fran6co/angular.js
freewind/angular.js
gaboom/angular.js
gijs/angular.js
girikudlur/angular.js
groner/angular.js
gruber76/angular.js
gwoo/angular.js
hackreactor/angular.js
hardikdangar/angular.js
hjoest/angular.js
hkdobrev/angular.js
hoatle/angular.js
huangciyin/angular.js
huangweili/angular.js
huncent/angular.js
hwclass/angular.js
iammerrick/angular.js
ifedotov/angular.js
imaizumi8925/angular.js
imiborbas/angular.js
intelline/angular.js
jajberni/angular.js
jc1arke/angular.js
jeanielight/angular.js
jecons/angular.js
jimrenwick/angular.js
jjp/angular.js
johnlindquist/angular.js
joshkurz/angular.js
jromero75/angular.js
jsonxu/angular.js
kevan/angular.js
kevinelong/angular.js
kinglerzou/angular.js
kkurni/angular.js
kliu/angular.js
kotiya/angular.js
kyuff/angular.js
lamperwang/angular.js
leeight/angular.js
lobsang/angular.js
lrlopez/angular.js
lt1946/angular.js
ludicast/angular.js
lzlf007/angular.js
m13z/angular.js
maciejblinkbox/angular.js
mailtruck/angular.js
manuel-woelker/angular.js
mdolk/angular.js
mernen/angular.js
mgechev/angular.js
mhevery/angular.js
msgilligan/angular.js
nateabele/angular.js
nateflink/angular.js
neolf/angular.js
patcito/angular.js
pdswan/angular.js
petebacondarwin/angular.js
petrovalex/angular.js
phillipkregg/angular.js
phoo/angular.js
pmurias/angular.js
premblinkbox/angular.js
quangv/angular.js
rafa2000/angular.js
rafaalves/angular.js
rahu28/angular.js
recht/angular.js
redg1974/angular.js
ricardohbin/angular.js
rtnpro/angular.js
ruimonteiro84/angular.js
rulers/angular.js
rwaldron/angular.js
sahilmalik5/angular.js
sangam12345/angular.js
santosomar/angular.js
scuxiayiqian/angular.js
shuvozula/angular.js
shyblower/angular-ie7.js
sjhernes/angular.js
snicolai/angular.js
steinjak/angular.js
stephanebisson/angular.js
stevenp-git/angular.js
sum4me/angular.js
suneil/angular.js
supercool27/angular.js
superman-wrdh/angular.js
thegerr09/angular.js
thenyel/angular.js
thughes/angular.js
timothyx/angular.js
timthesinner/angular.js
tleruitte/angular.js
tobyreynold/angular.js
tonitt/angular.js
trochette/angular.js
unirgy/angular.js
vibster/angular.js
vincentferniot/angular.js
vingo/angular.js
virtualSharif/angular.js
vkoroslev/angular.js
vojtajina/angular.js
witkai/angular.js
woodie/angular.js
wuxq/angular.js
xiehekun/angular.js
xrchen/angular.js
yanneves/angular.js
ysiadf/angular.js
yyx990803/angular.js
zfleet/angular.js
zhangruimin/angular.js
ziakina/angular.js
Nothing to show
base: 2563ff7ba92d
head repository: angular/angular.js
Choose a Head Repository
angular/angular.js
Anuj16/angular.js
ArslanRafique/angular.js
DeborahK/angular.js
EpokK/angular.js
HaoWu/angular.js
IgorMinar/angular.js
JKLFA/angular.js
KAUG/angular.js
Kaic-zz/angular.js
Metric7/angular.js
MikhailTatsky/angular.js
NAzT/angular.js
Narretz/angular.js
Partoo/angular.js
PeterBoesenberg/angular.js
PoshHsu/angular.js
ScxFiction/angular.js
SeanMBe/angular.js
Sharique-Hasan/angular.js
Shipow/angular.js
SjB/angular.js
Sophrinix/angular.js
SumitMunot/angular.js
TEHEK/angular.js
abhisec/angular.js
abnerlinan/angular.js
abrons/angular.js
acosme/angular.js
adam-singer/angular.js
addyosmani/angular.js
agborkowski/angular.js
ajperrins/angular.js
alexeagle/angular.js
alxross/angular.js
aminerahmouni/angular.js
amirhhz/angular.js
angeliaz/angular.js
angularjs-jp/angular.js
anjo/angular.js
arantius/angular.js
ardnet2/angular.js
arsh-co/angular.js
bartes/angular.js
bghanchi/angular.js
blinkbox/angular.js
blueslue/angular.js
boltz/angular.js
bolu/angular.js
briceburg/angular.js
brikou/angular.js
btford/angular.js
byplayer/angular.js
ca136/angular.js
calvinhuang/angular.js
cburgdorf/angular.js
chenermeng/angular.js
chris4403/angular.js
cleyshan/angular.js
codeinpeace/angular.js
colinfrei/angular.js
congmo/angular.js
crossbreeze/angular.js
csii/angular.js
cssgist/angular.js
danielfacanha/angular.js
danilopesouza/angular.js
dankrz/angular.js
dashersw/angular.js
dbinit/angular.js
dcu/angular.js
dhl/angular.js
dineshkummarc/angular.js
dolfly/angular.js
dydycloud/angular.js
eburley/angular.js
elfgoh/angular.js
esprehn/angular.js
fergaldoyle/angular.js
fingerskier/angular.js
flamilton/angular.js
fran6co/angular.js
freewind/angular.js
gaboom/angular.js
gijs/angular.js
girikudlur/angular.js
groner/angular.js
gruber76/angular.js
gwoo/angular.js
hackreactor/angular.js
hardikdangar/angular.js
hjoest/angular.js
hkdobrev/angular.js
hoatle/angular.js
huangciyin/angular.js
huangweili/angular.js
huncent/angular.js
hwclass/angular.js
iammerrick/angular.js
ifedotov/angular.js
imaizumi8925/angular.js
imiborbas/angular.js
intelline/angular.js
jajberni/angular.js
jc1arke/angular.js
jeanielight/angular.js
jecons/angular.js
jimrenwick/angular.js
jjp/angular.js
johnlindquist/angular.js
joshkurz/angular.js
jromero75/angular.js
jsonxu/angular.js
kevan/angular.js
kevinelong/angular.js
kinglerzou/angular.js
kkurni/angular.js
kliu/angular.js
kotiya/angular.js
kyuff/angular.js
lamperwang/angular.js
leeight/angular.js
lobsang/angular.js
lrlopez/angular.js
lt1946/angular.js
ludicast/angular.js
lzlf007/angular.js
m13z/angular.js
maciejblinkbox/angular.js
mailtruck/angular.js
manuel-woelker/angular.js
mdolk/angular.js
mernen/angular.js
mgechev/angular.js
mhevery/angular.js
msgilligan/angular.js
nateabele/angular.js
nateflink/angular.js
neolf/angular.js
patcito/angular.js
pdswan/angular.js
petebacondarwin/angular.js
petrovalex/angular.js
phillipkregg/angular.js
phoo/angular.js
pmurias/angular.js
premblinkbox/angular.js
quangv/angular.js
rafa2000/angular.js
rafaalves/angular.js
rahu28/angular.js
recht/angular.js
redg1974/angular.js
ricardohbin/angular.js
rtnpro/angular.js
ruimonteiro84/angular.js
rulers/angular.js
rwaldron/angular.js
sahilmalik5/angular.js
sangam12345/angular.js
santosomar/angular.js
scuxiayiqian/angular.js
shuvozula/angular.js
shyblower/angular-ie7.js
sjhernes/angular.js
snicolai/angular.js
steinjak/angular.js
stephanebisson/angular.js
stevenp-git/angular.js
sum4me/angular.js
suneil/angular.js
supercool27/angular.js
superman-wrdh/angular.js
thegerr09/angular.js
thenyel/angular.js
thughes/angular.js
timothyx/angular.js
timthesinner/angular.js
tleruitte/angular.js
tobyreynold/angular.js
tonitt/angular.js
trochette/angular.js
unirgy/angular.js
vibster/angular.js
vincentferniot/angular.js
vingo/angular.js
virtualSharif/angular.js
vkoroslev/angular.js
vojtajina/angular.js
witkai/angular.js
woodie/angular.js
wuxq/angular.js
xiehekun/angular.js
xrchen/angular.js
yanneves/angular.js
ysiadf/angular.js
yyx990803/angular.js
zfleet/angular.js
zhangruimin/angular.js
ziakina/angular.js
Nothing to show
compare: 2fc954d33a3a
  • 2 commits
  • 10 files changed
  • 0 commit comments
  • 1 contributor
Commits on Jan 12, 2016
Use `$animate.closeAndFlush()` to close all running animations.

Includes a fix that landed separately in the master branch:
a801df7
A bug in material has exposed that ngAnimate makes a copy of
the provided animation options twice. By making two copies,
the same DOM operations are performed during and at the end
of the animation. If the CSS classes being added/
removed contain existing transition code, then this will lead
to rendering issues.

Closes #13722
Closes #13578
@@ -56,6 +56,7 @@
$AnchorScrollProvider,
$AnimateProvider,
$CoreAnimateCssProvider,
$$CoreAnimateJsProvider,
$$CoreAnimateQueueProvider,
$$AnimateRunnerFactoryProvider,
$$AnimateAsyncRunFactoryProvider,
@@ -217,6 +218,7 @@ function publishExternalAPI(angular) {
$anchorScroll: $AnchorScrollProvider,
$animate: $AnimateProvider,
$animateCss: $CoreAnimateCssProvider,
$$animateJs: $$CoreAnimateJsProvider,
$$animateQueue: $$CoreAnimateQueueProvider,
$$AnimateRunner: $$AnimateRunnerFactoryProvider,
$$animateAsyncRun: $$AnimateAsyncRunFactoryProvider,
@@ -53,6 +53,10 @@ function prepareAnimateOptions(options) {
: {};
}

var $$CoreAnimateJsProvider = function() {
this.$get = function() {};
};

// this is prefixed with Core since it conflicts with
// the animateQueueProvider defined in ngAnimate/animateQueue.js
var $$CoreAnimateQueueProvider = function() {
@@ -15,10 +15,14 @@ var $CoreAnimateCssProvider = function() {
this.$get = ['$$rAF', '$q', '$$AnimateRunner', function($$rAF, $q, $$AnimateRunner) {

return function(element, initialOptions) {
// we always make a copy of the options since
// there should never be any side effects on
// the input data when running `$animateCss`.
var options = copy(initialOptions);
// all of the animation functions should create
// a copy of the options data, however, if a
// parent service has already created a copy then
// we should stick to using that
var options = initialOptions || {};
if (!options.$$prepared) {
options = copy(options);
}

// there is no point in applying the styles since
// there is no animation that goes on at all in
@@ -352,9 +352,9 @@ var $AnimateCssProvider = ['$animateProvider', function($animateProvider) {
var gcsStaggerLookup = createLocalCacheLookup();

this.$get = ['$window', '$$jqLite', '$$AnimateRunner', '$timeout',
'$$forceReflow', '$sniffer', '$$rAFScheduler', '$animate',
'$$forceReflow', '$sniffer', '$$rAFScheduler', '$$animateQueue',
function($window, $$jqLite, $$AnimateRunner, $timeout,
$$forceReflow, $sniffer, $$rAFScheduler, $animate) {
$$forceReflow, $sniffer, $$rAFScheduler, $$animateQueue) {

var applyAnimationClasses = applyAnimationClassesFactory($$jqLite);

@@ -447,21 +447,23 @@ var $AnimateCssProvider = ['$animateProvider', function($animateProvider) {
}

return function init(element, initialOptions) {
// we always make a copy of the options since
// there should never be any side effects on
// the input data when running `$animateCss`.
var options = copy(initialOptions);
// all of the animation functions should create
// a copy of the options data, however, if a
// parent service has already created a copy then
// we should stick to using that
var options = initialOptions || {};
if (!options.$$prepared) {
options = prepareAnimationOptions(copy(options));
}

var restoreStyles = {};
var node = getDomNode(element);
if (!node
|| !node.parentNode
|| !$animate.enabled()) {
|| !$$animateQueue.enabled()) {
return closeAndReturnNoopAnimator();
}

options = prepareAnimationOptions(options);

var temporaryStyles = [];
var classes = element.attr('class');
var styles = packageStyles(options);
@@ -11,6 +11,8 @@ var $$AnimateJsProvider = ['$animateProvider', function($animateProvider) {
var applyAnimationClasses = applyAnimationClassesFactory($$jqLite);
// $animateJs(element, 'enter');
return function(element, event, classes, options) {
var animationClosed = false;

// the `classes` argument is optional and if it is not used
// then the classes will be resolved from the element's className
// property as well as options.addClass/options.removeClass.
@@ -63,8 +65,32 @@ var $$AnimateJsProvider = ['$animateProvider', function($animateProvider) {
applyAnimationClasses(element, options);
}

function close() {
animationClosed = true;
applyOptions();
applyAnimationStyles(element, options);
}

var runner;

return {
$$willAnimate: true,
end: function() {
if (runner) {
runner.end();
} else {
close();
runner = new $$AnimateRunner();
runner.complete(true);
}
return runner;
},
start: function() {
if (runner) {
return runner;
}

runner = new $$AnimateRunner();
var closeActiveAnimations;
var chain = [];

@@ -89,8 +115,7 @@ var $$AnimateJsProvider = ['$animateProvider', function($animateProvider) {
});
}

var animationClosed = false;
var runner = new $$AnimateRunner({
runner.setHost({
end: function() {
endAnimations();
},
@@ -103,9 +128,7 @@ var $$AnimateJsProvider = ['$animateProvider', function($animateProvider) {
return runner;

function onComplete(success) {
animationClosed = true;
applyOptions();
applyAnimationStyles(element, options);
close(success);
runner.complete(success);
}

@@ -751,6 +751,15 @@ angular.mock.TzDate = function(offset, timestamp) {
angular.mock.TzDate.prototype = Date.prototype;
/* jshint +W101 */


/**
* @ngdoc service
* @name $animate
*
* @description
* Mock implementation of the {@link ng.$animate `$animate`} service. Exposes two additional methods
* for testing animations.
*/
angular.mock.animate = angular.module('ngAnimateMock', ['ng'])

.config(['$provide', function($provide) {
@@ -783,9 +792,50 @@ angular.mock.animate = angular.module('ngAnimateMock', ['ng'])
return queueFn;
});

$provide.decorator('$animate', ['$delegate', '$timeout', '$browser', '$$rAF',
$provide.decorator('$$animateJs', ['$delegate', function($delegate) {
var runners = [];

var animateJsConstructor = function() {
var animator = $delegate.apply($delegate, arguments);
// If no javascript animation is found, animator is undefined
if (animator) {
runners.push(animator);
}
return animator;
};

animateJsConstructor.$closeAndFlush = function() {
runners.forEach(function(runner) {
runner.end();
});
runners = [];
};

return animateJsConstructor;
}]);

$provide.decorator('$animateCss', ['$delegate', function($delegate) {
var runners = [];

var animateCssConstructor = function(element, options) {
var animator = $delegate(element, options);
runners.push(animator);
return animator;
};

animateCssConstructor.$closeAndFlush = function() {
runners.forEach(function(runner) {
runner.end();
});
runners = [];
};

return animateCssConstructor;
}]);

$provide.decorator('$animate', ['$delegate', '$timeout', '$browser', '$$rAF', '$animateCss', '$$animateJs',
'$$forceReflow', '$$animateAsyncRun', '$rootScope',
function($delegate, $timeout, $browser, $$rAF,
function($delegate, $timeout, $browser, $$rAF, $animateCss, $$animateJs,
$$forceReflow, $$animateAsyncRun, $rootScope) {
var animate = {
queue: [],
@@ -797,7 +847,35 @@ angular.mock.animate = angular.module('ngAnimateMock', ['ng'])
return $$forceReflow.totalReflows;
},
enabled: $delegate.enabled,
flush: function() {
/**
* @ngdoc method
* @name $animate#closeAndFlush
* @description
*
* This method will close all pending animations (both {@link ngAnimate#javascript-based-animations Javascript}
* and {@link ngAnimate.$animateCss CSS}) and it will also flush any remaining animation frames and/or callbacks.
*/
closeAndFlush: function() {
// we allow the flush command to swallow the errors
// because depending on whether CSS or JS animations are
// used, there may not be a RAF flush. The primary flush
// at the end of this function must throw an exception
// because it will track if there were pending animations
this.flush(true);
$animateCss.$closeAndFlush();
$$animateJs.$closeAndFlush();
this.flush();
},
/**
* @ngdoc method
* @name $animate#flush
* @description
*
* This method is used to flush the pending callbacks and animation frames to either start
* an animation or conclude an animation. Note that this will not actually close an
* actively running animation (see {@link ngMock.$animate#closeAndFlush `closeAndFlush()`} for that).
*/
flush: function(hideErrors) {
$rootScope.$digest();

var doNextRun, somethingFlushed = false;
@@ -814,7 +892,7 @@ angular.mock.animate = angular.module('ngAnimateMock', ['ng'])
}
} while (doNextRun);

if (!somethingFlushed) {
if (!somethingFlushed && !hideErrors) {
throw new Error('No pending animations ready to be closed or flushed');
}

@@ -31,6 +31,28 @@ describe("$animateCss", function() {
expect(copiedOptions).toEqual(initialOptions);
}));

it("should not create a copy of the provided options if they have already been prepared earlier",
inject(function($animateCss, $$rAF) {

var options = {
from: { height: '50px' },
to: { width: '50px' },
addClass: 'one',
removeClass: 'two'
};

options.$$prepared = true;
var runner = $animateCss(element, options).start();
runner.end();

$$rAF.flush();

expect(options.addClass).toBeFalsy();
expect(options.removeClass).toBeFalsy();
expect(options.to).toBeFalsy();
expect(options.from).toBeFalsy();
}));

it("should apply the provided [from] CSS to the element", inject(function($animateCss) {
$animateCss(element, { from: { height: '50px' }}).start();
expect(element.css('height')).toBe('50px');
@@ -2036,6 +2036,28 @@ describe("ngAnimate $animateCss", function() {
expect(copiedOptions).toEqual(initialOptions);
}));

it("should not create a copy of the provided options if they have already been prepared earlier",
inject(function($animate, $animateCss) {

var options = {
from: { height: '50px' },
to: { width: '50px' },
addClass: 'one',
removeClass: 'two'
};

options.$$prepared = true;
var runner = $animateCss(element, options).start();
runner.end();

$animate.flush();

expect(options.addClass).toBeFalsy();
expect(options.removeClass).toBeFalsy();
expect(options.to).toBeFalsy();
expect(options.from).toBeFalsy();
}));

describe("[$$skipPreparationClasses]", function() {
it('should not apply and remove the preparation classes to the element when true',
inject(function($animateCss) {
@@ -28,6 +28,27 @@ describe('ngAnimate integration tests', function() {
describe('CSS animations', function() {
if (!browserSupportsCssAnimations()) return;

it("should only create a single copy of the provided animation options",
inject(function($rootScope, $rootElement, $animate) {

ss.addRule('.animate-me', 'transition:2s linear all;');

var element = jqLite('<div class="animate-me"></div>');
html(element);

var myOptions = {to: { 'color': 'red' }};

var spy = spyOn(window, 'copy');
expect(spy).not.toHaveBeenCalled();

var animation = $animate.leave(element, myOptions);
$rootScope.$digest();
$animate.flush();

expect(spy).toHaveBeenCalledOnce();
dealoc(element);
}));

they('should render an $prop animation',
['enter', 'leave', 'move', 'addClass', 'removeClass', 'setClass'], function(event) {

@@ -390,6 +411,32 @@ describe('ngAnimate integration tests', function() {
expect(element).not.toHaveClass('hide');
}));

it('should handle ng-if & ng-class with a class that is removed before its add animation has concluded', function() {
inject(function($animate, $rootScope, $compile, $timeout, $$rAF) {

ss.addRule('.animate-me', 'transition: all 0.5s;');

element = jqLite('<section><div ng-if="true" class="animate-me" ng-class="{' +
'red: red,' +
'blue: blue' +
'}"></div></section>');

html(element);
$rootScope.blue = true;
$rootScope.red = true;
$compile(element)($rootScope);
$rootScope.$digest();

var child = element.find('div');

// Trigger class removal before the add animation has been concluded
$rootScope.blue = false;
$animate.closeAndFlush();

expect(child).toHaveClass('red');
expect(child).not.toHaveClass('blue');
});
});
});

describe('JS animations', function() {

No commit comments for this range

You can’t perform that action at this time.