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

Commit 9227a5d

Browse files
Isaac Shapirabtford
Isaac Shapira
authored andcommittedJun 2, 2014
fix(ngAnimate): $animate methods should accept native dom elements
1 parent fc6ce59 commit 9227a5d

File tree

2 files changed

+170
-2
lines changed

2 files changed

+170
-2
lines changed
 

‎src/ngAnimate/animate.js

+17-1
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,10 @@ angular.module('ngAnimate', ['ng'])
289289
}
290290
}
291291

292+
function prepareElement(element) {
293+
return element && angular.element(element);
294+
}
295+
292296
function stripCommentsFromElement(element) {
293297
return angular.element(extractElementNode(element));
294298
}
@@ -544,6 +548,10 @@ angular.module('ngAnimate', ['ng'])
544548
* @param {function()=} doneCallback the callback function that will be called once the animation is complete
545549
*/
546550
enter : function(element, parentElement, afterElement, doneCallback) {
551+
element = angular.element(element);
552+
parentElement = prepareElement(parentElement);
553+
afterElement = prepareElement(afterElement);
554+
547555
this.enabled(false, element);
548556
$delegate.enter(element, parentElement, afterElement);
549557
$rootScope.$$postDigest(function() {
@@ -580,6 +588,7 @@ angular.module('ngAnimate', ['ng'])
580588
* @param {function()=} doneCallback the callback function that will be called once the animation is complete
581589
*/
582590
leave : function(element, doneCallback) {
591+
element = angular.element(element);
583592
cancelChildAnimations(element);
584593
this.enabled(false, element);
585594
$rootScope.$$postDigest(function() {
@@ -620,6 +629,10 @@ angular.module('ngAnimate', ['ng'])
620629
* @param {function()=} doneCallback the callback function that will be called once the animation is complete
621630
*/
622631
move : function(element, parentElement, afterElement, doneCallback) {
632+
element = angular.element(element);
633+
parentElement = prepareElement(parentElement);
634+
afterElement = prepareElement(afterElement);
635+
623636
cancelChildAnimations(element);
624637
this.enabled(false, element);
625638
$delegate.move(element, parentElement, afterElement);
@@ -659,6 +672,7 @@ angular.module('ngAnimate', ['ng'])
659672
* @param {function()=} doneCallback the callback function that will be called once the animation is complete
660673
*/
661674
addClass : function(element, className, doneCallback) {
675+
element = angular.element(element);
662676
element = stripCommentsFromElement(element);
663677
performAnimation('addClass', className, element, null, null, function() {
664678
$delegate.addClass(element, className);
@@ -695,6 +709,7 @@ angular.module('ngAnimate', ['ng'])
695709
* @param {function()=} doneCallback the callback function that will be called once the animation is complete
696710
*/
697711
removeClass : function(element, className, doneCallback) {
712+
element = angular.element(element);
698713
element = stripCommentsFromElement(element);
699714
performAnimation('removeClass', className, element, null, null, function() {
700715
$delegate.removeClass(element, className);
@@ -716,6 +731,7 @@ angular.module('ngAnimate', ['ng'])
716731
* CSS classes have been set on the element
717732
*/
718733
setClass : function(element, add, remove, doneCallback) {
734+
element = angular.element(element);
719735
element = stripCommentsFromElement(element);
720736
performAnimation('setClass', [add, remove], element, null, null, function() {
721737
$delegate.setClass(element, add, remove);
@@ -728,7 +744,7 @@ angular.module('ngAnimate', ['ng'])
728744
* @function
729745
*
730746
* @param {boolean=} value If provided then set the animation on or off.
731-
* @param {DOMElement=} element If provided then the element will be used to represent the enable/disable operation
747+
* @param {DOMElement} element If provided then the element will be used to represent the enable/disable operation
732748
* @return {boolean} Current animation state.
733749
*
734750
* @description

‎test/ngAnimate/animateSpec.js

+153-1
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,24 @@ describe("ngAnimate", function() {
290290
expect(element.contents().length).toBe(1);
291291
}));
292292

293+
it("should animate the enter animation event with native dom elements",
294+
inject(function($animate, $rootScope, $sniffer, $timeout) {
295+
element[0].removeChild(child[0]);
296+
297+
expect(element.contents().length).toBe(0);
298+
$animate.enter(child[0], element[0]);
299+
$rootScope.$digest();
300+
301+
if($sniffer.transitions) {
302+
$animate.triggerReflow();
303+
expect(child.hasClass('ng-enter')).toBe(true);
304+
expect(child.hasClass('ng-enter-active')).toBe(true);
305+
browserTrigger(element, 'transitionend', { timeStamp: Date.now() + 1000, elapsedTime: 1 });
306+
}
307+
308+
expect(element.contents().length).toBe(1);
309+
}));
310+
293311

294312
it("should animate the leave animation event",
295313
inject(function($animate, $rootScope, $sniffer, $timeout) {
@@ -308,6 +326,22 @@ describe("ngAnimate", function() {
308326
expect(element.contents().length).toBe(0);
309327
}));
310328

329+
it("should animate the leave animation event with native dom elements",
330+
inject(function($animate, $rootScope, $sniffer, $timeout) {
331+
332+
expect(element.contents().length).toBe(1);
333+
$animate.leave(child[0]);
334+
$rootScope.$digest();
335+
336+
if($sniffer.transitions) {
337+
$animate.triggerReflow();
338+
expect(child.hasClass('ng-leave')).toBe(true);
339+
expect(child.hasClass('ng-leave-active')).toBe(true);
340+
browserTrigger(child,'transitionend', { timeStamp: Date.now() + 1000, elapsedTime: 1 });
341+
}
342+
343+
expect(element.contents().length).toBe(0);
344+
}));
311345

312346
it("should animate the move animation event",
313347
inject(function($animate, $compile, $rootScope, $timeout, $sniffer) {
@@ -328,6 +362,24 @@ describe("ngAnimate", function() {
328362
expect(element.text()).toBe('21');
329363
}));
330364

365+
it("should animate the move animation event with native dom elements",
366+
inject(function($animate, $compile, $rootScope, $timeout, $sniffer) {
367+
368+
$rootScope.$digest();
369+
element.empty();
370+
371+
var child1 = $compile('<div>1</div>')($rootScope);
372+
var child2 = $compile('<div>2</div>')($rootScope);
373+
element.append(child1);
374+
element.append(child2);
375+
expect(element.text()).toBe('12');
376+
$animate.move(child1[0], element[0], child2[0]);
377+
$rootScope.$digest();
378+
if($sniffer.transitions) {
379+
$animate.triggerReflow();
380+
}
381+
expect(element.text()).toBe('21');
382+
}));
331383

332384
it("should animate the show animation event",
333385
inject(function($animate, $rootScope, $sniffer, $timeout) {
@@ -347,7 +399,6 @@ describe("ngAnimate", function() {
347399
expect(child).toBeShown();
348400
}));
349401

350-
351402
it("should animate the hide animation event",
352403
inject(function($animate, $rootScope, $sniffer, $timeout) {
353404

@@ -401,6 +452,43 @@ describe("ngAnimate", function() {
401452
});
402453
});
403454

455+
it("should exclusively animate the setClass animation event with native dom elements", function() {
456+
var count = 0, fallback = jasmine.createSpy('callback');
457+
module(function($animateProvider) {
458+
$animateProvider.register('.classify', function() {
459+
return {
460+
beforeAddClass : fallback,
461+
addClass : fallback,
462+
beforeRemoveClass : fallback,
463+
removeClass : fallback,
464+
465+
beforeSetClass : function(element, add, remove, done) {
466+
count++;
467+
expect(add).toBe('yes');
468+
expect(remove).toBe('no');
469+
done();
470+
},
471+
setClass : function(element, add, remove, done) {
472+
count++;
473+
expect(add).toBe('yes');
474+
expect(remove).toBe('no');
475+
done();
476+
}
477+
};
478+
});
479+
});
480+
inject(function($animate, $rootScope, $sniffer, $timeout) {
481+
child.attr('class','classify no');
482+
$animate.setClass(child[0], 'yes', 'no');
483+
$animate.triggerReflow();
484+
485+
expect(child.hasClass('yes')).toBe(true);
486+
expect(child.hasClass('no')).toBe(false);
487+
expect(count).toBe(2);
488+
489+
expect(fallback).not.toHaveBeenCalled();
490+
});
491+
});
404492

405493
it("should delegate down to addClass/removeClass if a setClass animation is not found", function() {
406494
var count = 0;
@@ -2003,6 +2091,39 @@ describe("ngAnimate", function() {
20032091
expect(captured).toBe('addClass-some-class');
20042092
}));
20052093

2094+
it("should perform the animation if passed native dom element",
2095+
inject(function($animate, $rootScope, $sniffer, $rootElement, $timeout, $browser) {
2096+
2097+
var element = jqLite('<div class="klassy"></div>');
2098+
$rootElement.append(element);
2099+
body.append($rootElement);
2100+
2101+
//skipped animations
2102+
captured = 'none';
2103+
$animate.removeClass(element[0], 'some-class');
2104+
expect(element.hasClass('some-class')).toBe(false);
2105+
expect(captured).toBe('none');
2106+
2107+
element.addClass('some-class');
2108+
2109+
captured = 'nothing';
2110+
$animate.addClass(element[0], 'some-class');
2111+
expect(captured).toBe('nothing');
2112+
expect(element.hasClass('some-class')).toBe(true);
2113+
2114+
//actual animations
2115+
captured = 'none';
2116+
$animate.removeClass(element[0], 'some-class');
2117+
$animate.triggerReflow();
2118+
expect(element.hasClass('some-class')).toBe(false);
2119+
expect(captured).toBe('removeClass-some-class');
2120+
2121+
captured = 'nothing';
2122+
$animate.addClass(element[0], 'some-class');
2123+
$animate.triggerReflow();
2124+
expect(element.hasClass('some-class')).toBe(true);
2125+
expect(captured).toBe('addClass-some-class');
2126+
}));
20062127

20072128
it("should add and remove CSS classes after an animation even if no animation is present",
20082129
inject(function($animate, $rootScope, $sniffer, $rootElement) {
@@ -2132,6 +2253,37 @@ describe("ngAnimate", function() {
21322253
expect(signature).toBe('XY');
21332254
}));
21342255

2256+
it("should properly execute JS animations if passed native dom element",
2257+
inject(function($animate, $rootScope, $sniffer, $rootElement, $timeout) {
2258+
2259+
var parent = jqLite('<div><span></span></div>');
2260+
$rootElement.append(parent);
2261+
body.append($rootElement);
2262+
var element = jqLite(parent.find('span'));
2263+
2264+
var signature = '';
2265+
2266+
$animate.addClass(element[0],'klassy', function() {
2267+
signature += 'X';
2268+
});
2269+
$animate.triggerReflow();
2270+
2271+
$timeout.flush(500);
2272+
2273+
expect(element.hasClass('klassy')).toBe(true);
2274+
2275+
$animate.removeClass(element[0],'klassy', function() {
2276+
signature += 'Y';
2277+
});
2278+
$animate.triggerReflow();
2279+
2280+
$timeout.flush(3000);
2281+
2282+
expect(element.hasClass('klassy')).toBe(false);
2283+
2284+
$animate.triggerCallbacks();
2285+
expect(signature).toBe('XY');
2286+
}));
21352287

21362288
it("should properly execute CSS animations/transitions and use callbacks when using addClass / removeClass",
21372289
inject(function($animate, $rootScope, $sniffer, $rootElement, $timeout) {

0 commit comments

Comments
 (0)