Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit f799435

Browse files
committed
fix(ngAnimate): let $animate.cancel() reject the runner promise
1 parent 41d5c90 commit f799435

File tree

3 files changed

+341
-14
lines changed

3 files changed

+341
-14
lines changed

src/ng/animate.js

Lines changed: 149 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -464,13 +464,150 @@ var $AnimateProvider = ['$provide', /** @this */ function($provide) {
464464
* @ngdoc method
465465
* @name $animate#cancel
466466
* @kind function
467-
* @description Cancels the provided animation.
468-
*
469-
* @param {Promise} animationPromise The animation promise that is returned when an animation is started.
467+
* @description Cancels the provided animation and applies the end state of the animation.
468+
* Note that this does not cancel the underlying operation, e.g. the setting of classes or
469+
* adding the element to the DOM.
470+
*
471+
* @param {animationRunner} animationRunner An animation runner returned by an $animate function.
472+
*
473+
* @example
474+
<example module="animationExample" deps="angular-animate.js" animations="true" name="animate-cancel">
475+
<file name="app.js">
476+
angular.module('animationExample', ['ngAnimate']).component('cancelExample', {
477+
templateUrl: 'template.html',
478+
controller: function($element, $animate) {
479+
this.runner = null;
480+
481+
this.addClass = function() {
482+
this.runner = $animate.addClass($element.find('span'), 'red');
483+
var ctrl = this;
484+
this.runner.finally(function() {
485+
ctrl.runner = null;
486+
});
487+
};
488+
489+
this.removeClass = function() {
490+
this.runner = $animate.removeClass($element.find('span'), 'red');
491+
var ctrl = this;
492+
this.runner.finally(function() {
493+
ctrl.runner = null;
494+
});
495+
};
496+
497+
this.cancel = function() {
498+
$animate.cancel(this.runner);
499+
};
500+
501+
this.enter = function() {
502+
var ctrl = this;
503+
504+
this.runner = $animate.enter(this.element, null, $element.find('span'));
505+
this.runner.catch(function(e) {
506+
console.log('catch', e);
507+
ctrl.cancelCount++;
508+
});
509+
};
510+
511+
this.leave = function() {
512+
var ctrl = this;
513+
514+
this.runner = $animate.leave(this.element);
515+
this.runner.catch(function(e) {
516+
ctrl.cancelCount++;
517+
});
518+
};
519+
}
520+
});
521+
</file>
522+
<file name="template.html">
523+
<p>
524+
<button id="add" ng-click="$ctrl.addClass()">Add</button>
525+
<button ng-click="$ctrl.removeClass()">Remove</button>
526+
<button ng-click="$ctrl.enter()">Enter</button>
527+
<button ng-click="$ctrl.leave()">Leave</button>
528+
<br>
529+
<button id="cancel" ng-click="$ctrl.cancel()" ng-disabled="!$ctrl.runner">Cancel</button>
530+
<br>
531+
<span id="target">CSS-Animated Text</span>
532+
</p>
533+
</file>
534+
<file name="index.html">
535+
<cancel-example></cancel-example>
536+
</file>
537+
<file name="style.css">
538+
.red-add, .red-remove {
539+
transition: all 4s cubic-bezier(0.250, 0.460, 0.450, 0.940);
540+
}
541+
542+
.red,
543+
.red-add.red-add-active {
544+
color: #FF0000;
545+
font-size: 3em;
546+
}
547+
548+
.red-remove.red-remove-active {
549+
font-size: 1em;
550+
color: black;
551+
}
552+
553+
.animate-if {
554+
background:white;
555+
border:1px solid black;
556+
padding:10px;
557+
}
558+
559+
.animate-if.ng-enter, .animate-if.ng-leave {
560+
transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 5s;
561+
}
562+
563+
.animate-if.ng-enter,
564+
.animate-if.ng-leave.ng-leave-active {
565+
opacity:0;
566+
background: red;
567+
}
568+
569+
.animate-if.ng-leave,
570+
.animate-if.ng-enter.ng-enter-active {
571+
opacity:1;
572+
background: white;
573+
}
574+
575+
</file>
576+
<file name="protractor.js" type="protractor">
577+
578+
it('should cancel the animation', function() {
579+
//Enable animations (we disable them by default, see protractor-shared-conf.js)
580+
element(by.css('body')).allowAnimations(true);
581+
// CSS transitions use $timeout, for which Protractor by default to finish,
582+
// before executing the next action.
583+
// In this case, this would mean that the click on "Cancel" is only executed
584+
// after the transition has finished
585+
browser.waitForAngularEnabled(false);
586+
587+
var target = element(by.id('target'));
588+
589+
element(by.buttonText('Add')).click();
590+
591+
var classes = target.getAttribute('class');
592+
593+
expect(classes).toContain('ng-animate');
594+
expect(classes).toContain('red-add-active');
595+
expect(classes).toContain('red');
596+
597+
element(by.buttonText('Cancel')).click();
598+
599+
classes = target.getAttribute('class');
600+
601+
expect(classes).not.toContain('ng-animate');
602+
expect(classes).not.toContain('red-add-active');
603+
expect(classes).toContain('red');
604+
});
605+
</file>
606+
</example>
470607
*/
471608
cancel: function(runner) {
472-
if (runner.end) {
473-
runner.end();
609+
if (runner.cancel) {
610+
runner.cancel();
474611
}
475612
},
476613

@@ -496,7 +633,7 @@ var $AnimateProvider = ['$provide', /** @this */ function($provide) {
496633
* - **removeClass** - `{string}` - space-separated CSS classes to remove from element
497634
* - **to** - `{Object}` - CSS properties & values at end of animation. Must have matching `from`
498635
*
499-
* @return {Promise} the animation callback promise
636+
* @return {Runner} the animation runner
500637
*/
501638
enter: function(element, parent, after, options) {
502639
parent = parent && jqLite(parent);
@@ -528,7 +665,7 @@ var $AnimateProvider = ['$provide', /** @this */ function($provide) {
528665
* - **removeClass** - `{string}` - space-separated CSS classes to remove from element
529666
* - **to** - `{Object}` - CSS properties & values at end of animation. Must have matching `from`
530667
*
531-
* @return {Promise} the animation callback promise
668+
* @return {Runner} the animation runner
532669
*/
533670
move: function(element, parent, after, options) {
534671
parent = parent && jqLite(parent);
@@ -555,7 +692,7 @@ var $AnimateProvider = ['$provide', /** @this */ function($provide) {
555692
* - **removeClass** - `{string}` - space-separated CSS classes to remove from element
556693
* - **to** - `{Object}` - CSS properties & values at end of animation. Must have matching `from`
557694
*
558-
* @return {Promise} the animation callback promise
695+
* @return {Runner} the animation runner
559696
*/
560697
leave: function(element, options) {
561698
return $$animateQueue.push(element, 'leave', prepareAnimateOptions(options), function() {
@@ -585,7 +722,7 @@ var $AnimateProvider = ['$provide', /** @this */ function($provide) {
585722
* - **removeClass** - `{string}` - space-separated CSS classes to remove from element
586723
* - **to** - `{Object}` - CSS properties & values at end of animation. Must have matching `from`
587724
*
588-
* @return {Promise} the animation callback promise
725+
* @return {Runner} animationRunner the animation runner
589726
*/
590727
addClass: function(element, className, options) {
591728
options = prepareAnimateOptions(options);
@@ -615,7 +752,7 @@ var $AnimateProvider = ['$provide', /** @this */ function($provide) {
615752
* - **removeClass** - `{string}` - space-separated CSS classes to remove from element
616753
* - **to** - `{Object}` - CSS properties & values at end of animation. Must have matching `from`
617754
*
618-
* @return {Promise} the animation callback promise
755+
* @return {Runner} the animation runner
619756
*/
620757
removeClass: function(element, className, options) {
621758
options = prepareAnimateOptions(options);
@@ -646,7 +783,7 @@ var $AnimateProvider = ['$provide', /** @this */ function($provide) {
646783
* - **removeClass** - `{string}` - space-separated CSS classes to remove from element
647784
* - **to** - `{Object}` - CSS properties & values at end of animation. Must have matching `from`
648785
*
649-
* @return {Promise} the animation callback promise
786+
* @return {Runner} the animation runner
650787
*/
651788
setClass: function(element, add, remove, options) {
652789
options = prepareAnimateOptions(options);
@@ -693,7 +830,7 @@ var $AnimateProvider = ['$provide', /** @this */ function($provide) {
693830
* - **removeClass** - `{string}` - space-separated CSS classes to remove from element
694831
* - **to** - `{Object}` - CSS properties & values at end of animation. Must have matching `from`
695832
*
696-
* @return {Promise} the animation callback promise
833+
* @return {Runner} the animation runner
697834
*/
698835
animate: function(element, from, to, className, options) {
699836
options = prepareAnimateOptions(options);

src/ngAnimate/animateCss.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -722,8 +722,8 @@ var $AnimateCssProvider = ['$animateProvider', /** @this */ function($animatePro
722722
}
723723
$$jqLite.removeClass(element, activeClasses);
724724

725-
blockKeyframeAnimations(node, false);
726-
blockTransitions(node, false);
725+
// blockKeyframeAnimations(node, false);
726+
// blockTransitions(node, false);
727727

728728
forEach(temporaryStyles, function(entry) {
729729
// There is only one way to remove inline style properties entirely from elements.

0 commit comments

Comments
 (0)