Skip to content

Commit 6090e0c

Browse files
Merge pull request #159 from angular/master
Update upstream
2 parents bee75c2 + 0e26197 commit 6090e0c

12 files changed

+408
-86
lines changed

angularFiles.js

+1
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ var angularFiles = {
104104
'src/ngAnimate/animateJs.js',
105105
'src/ngAnimate/animateJsDriver.js',
106106
'src/ngAnimate/animateQueue.js',
107+
'src/ngAnimate/animateCache.js',
107108
'src/ngAnimate/animation.js',
108109
'src/ngAnimate/ngAnimateSwap.js',
109110
'src/ngAnimate/module.js'

src/ngAnimate/.eslintrc.json

+1
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@
7373
/* ngAnimate directives/services */
7474
"ngAnimateSwapDirective": true,
7575
"$$rAFSchedulerFactory": true,
76+
"$$AnimateCacheProvider": true,
7677
"$$AnimateChildrenDirective": true,
7778
"$$AnimateQueueProvider": true,
7879
"$$AnimationProvider": true,

src/ngAnimate/animateCache.js

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
'use strict';
2+
3+
/** @this */
4+
var $$AnimateCacheProvider = function() {
5+
6+
var KEY = '$$ngAnimateParentKey';
7+
var parentCounter = 0;
8+
var cache = Object.create(null);
9+
10+
this.$get = [function() {
11+
return {
12+
cacheKey: function(node, method, addClass, removeClass) {
13+
var parentNode = node.parentNode;
14+
var parentID = parentNode[KEY] || (parentNode[KEY] = ++parentCounter);
15+
var parts = [parentID, method, node.getAttribute('class')];
16+
if (addClass) {
17+
parts.push(addClass);
18+
}
19+
if (removeClass) {
20+
parts.push(removeClass);
21+
}
22+
return parts.join(' ');
23+
},
24+
25+
containsCachedAnimationWithoutDuration: function(key) {
26+
var entry = cache[key];
27+
28+
// nothing cached, so go ahead and animate
29+
// otherwise it should be a valid animation
30+
return (entry && !entry.isValid) || false;
31+
},
32+
33+
flush: function() {
34+
cache = Object.create(null);
35+
},
36+
37+
count: function(key) {
38+
var entry = cache[key];
39+
return entry ? entry.total : 0;
40+
},
41+
42+
get: function(key) {
43+
var entry = cache[key];
44+
return entry && entry.value;
45+
},
46+
47+
put: function(key, value, isValid) {
48+
if (!cache[key]) {
49+
cache[key] = { total: 1, value: value, isValid: isValid };
50+
} else {
51+
cache[key].total++;
52+
cache[key].value = value;
53+
}
54+
}
55+
};
56+
}];
57+
};

src/ngAnimate/animateCss.js

+34-58
Original file line numberDiff line numberDiff line change
@@ -304,33 +304,6 @@ function getCssTransitionDurationStyle(duration, applyOnlyDuration) {
304304
return [style, value];
305305
}
306306

307-
function createLocalCacheLookup() {
308-
var cache = Object.create(null);
309-
return {
310-
flush: function() {
311-
cache = Object.create(null);
312-
},
313-
314-
count: function(key) {
315-
var entry = cache[key];
316-
return entry ? entry.total : 0;
317-
},
318-
319-
get: function(key) {
320-
var entry = cache[key];
321-
return entry && entry.value;
322-
},
323-
324-
put: function(key, value) {
325-
if (!cache[key]) {
326-
cache[key] = { total: 1, value: value };
327-
} else {
328-
cache[key].total++;
329-
}
330-
}
331-
};
332-
}
333-
334307
// we do not reassign an already present style value since
335308
// if we detect the style property value again we may be
336309
// detecting styles that were added via the `from` styles.
@@ -349,26 +322,16 @@ function registerRestorableStyles(backup, node, properties) {
349322
}
350323

351324
var $AnimateCssProvider = ['$animateProvider', /** @this */ function($animateProvider) {
352-
var gcsLookup = createLocalCacheLookup();
353-
var gcsStaggerLookup = createLocalCacheLookup();
354325

355-
this.$get = ['$window', '$$jqLite', '$$AnimateRunner', '$timeout',
326+
this.$get = ['$window', '$$jqLite', '$$AnimateRunner', '$timeout', '$$animateCache',
356327
'$$forceReflow', '$sniffer', '$$rAFScheduler', '$$animateQueue',
357-
function($window, $$jqLite, $$AnimateRunner, $timeout,
328+
function($window, $$jqLite, $$AnimateRunner, $timeout, $$animateCache,
358329
$$forceReflow, $sniffer, $$rAFScheduler, $$animateQueue) {
359330

360331
var applyAnimationClasses = applyAnimationClassesFactory($$jqLite);
361332

362-
var parentCounter = 0;
363-
function gcsHashFn(node, extraClasses) {
364-
var KEY = '$$ngAnimateParentKey';
365-
var parentNode = node.parentNode;
366-
var parentID = parentNode[KEY] || (parentNode[KEY] = ++parentCounter);
367-
return parentID + '-' + node.getAttribute('class') + '-' + extraClasses;
368-
}
369-
370-
function computeCachedCssStyles(node, className, cacheKey, properties) {
371-
var timings = gcsLookup.get(cacheKey);
333+
function computeCachedCssStyles(node, className, cacheKey, allowNoDuration, properties) {
334+
var timings = $$animateCache.get(cacheKey);
372335

373336
if (!timings) {
374337
timings = computeCssStyles($window, node, properties);
@@ -377,20 +340,26 @@ var $AnimateCssProvider = ['$animateProvider', /** @this */ function($animatePro
377340
}
378341
}
379342

343+
// if a css animation has no duration we
344+
// should mark that so that repeated addClass/removeClass calls are skipped
345+
var hasDuration = allowNoDuration || (timings.transitionDuration > 0 || timings.animationDuration > 0);
346+
380347
// we keep putting this in multiple times even though the value and the cacheKey are the same
381348
// because we're keeping an internal tally of how many duplicate animations are detected.
382-
gcsLookup.put(cacheKey, timings);
349+
$$animateCache.put(cacheKey, timings, hasDuration);
350+
383351
return timings;
384352
}
385353

386354
function computeCachedCssStaggerStyles(node, className, cacheKey, properties) {
387355
var stagger;
356+
var staggerCacheKey = 'stagger-' + cacheKey;
388357

389358
// if we have one or more existing matches of matching elements
390359
// containing the same parent + CSS styles (which is how cacheKey works)
391360
// then staggering is possible
392-
if (gcsLookup.count(cacheKey) > 0) {
393-
stagger = gcsStaggerLookup.get(cacheKey);
361+
if ($$animateCache.count(cacheKey) > 0) {
362+
stagger = $$animateCache.get(staggerCacheKey);
394363

395364
if (!stagger) {
396365
var staggerClassName = pendClasses(className, '-stagger');
@@ -405,7 +374,7 @@ var $AnimateCssProvider = ['$animateProvider', /** @this */ function($animatePro
405374

406375
$$jqLite.removeClass(node, staggerClassName);
407376

408-
gcsStaggerLookup.put(cacheKey, stagger);
377+
$$animateCache.put(staggerCacheKey, stagger, true);
409378
}
410379
}
411380

@@ -416,8 +385,7 @@ var $AnimateCssProvider = ['$animateProvider', /** @this */ function($animatePro
416385
function waitUntilQuiet(callback) {
417386
rafWaitQueue.push(callback);
418387
$$rAFScheduler.waitUntilQuiet(function() {
419-
gcsLookup.flush();
420-
gcsStaggerLookup.flush();
388+
$$animateCache.flush();
421389

422390
// DO NOT REMOVE THIS LINE OR REFACTOR OUT THE `pageWidth` variable.
423391
// PLEASE EXAMINE THE `$$forceReflow` service to understand why.
@@ -432,8 +400,8 @@ var $AnimateCssProvider = ['$animateProvider', /** @this */ function($animatePro
432400
});
433401
}
434402

435-
function computeTimings(node, className, cacheKey) {
436-
var timings = computeCachedCssStyles(node, className, cacheKey, DETECT_CSS_PROPERTIES);
403+
function computeTimings(node, className, cacheKey, allowNoDuration) {
404+
var timings = computeCachedCssStyles(node, className, cacheKey, allowNoDuration, DETECT_CSS_PROPERTIES);
437405
var aD = timings.animationDelay;
438406
var tD = timings.transitionDelay;
439407
timings.maxDelay = aD && tD
@@ -520,7 +488,6 @@ var $AnimateCssProvider = ['$animateProvider', /** @this */ function($animatePro
520488

521489
var preparationClasses = [structuralClassName, addRemoveClassName].join(' ').trim();
522490
var fullClassName = classes + ' ' + preparationClasses;
523-
var activeClasses = pendClasses(preparationClasses, ACTIVE_CLASS_SUFFIX);
524491
var hasToStyles = styles.to && Object.keys(styles.to).length > 0;
525492
var containsKeyframeAnimation = (options.keyframeStyle || '').length > 0;
526493

@@ -533,7 +500,12 @@ var $AnimateCssProvider = ['$animateProvider', /** @this */ function($animatePro
533500
return closeAndReturnNoopAnimator();
534501
}
535502

536-
var cacheKey, stagger;
503+
var stagger, cacheKey = $$animateCache.cacheKey(node, method, options.addClass, options.removeClass);
504+
if ($$animateCache.containsCachedAnimationWithoutDuration(cacheKey)) {
505+
preparationClasses = null;
506+
return closeAndReturnNoopAnimator();
507+
}
508+
537509
if (options.stagger > 0) {
538510
var staggerVal = parseFloat(options.stagger);
539511
stagger = {
@@ -543,7 +515,6 @@ var $AnimateCssProvider = ['$animateProvider', /** @this */ function($animatePro
543515
animationDuration: 0
544516
};
545517
} else {
546-
cacheKey = gcsHashFn(node, fullClassName);
547518
stagger = computeCachedCssStaggerStyles(node, preparationClasses, cacheKey, DETECT_STAGGER_CSS_PROPERTIES);
548519
}
549520

@@ -577,7 +548,7 @@ var $AnimateCssProvider = ['$animateProvider', /** @this */ function($animatePro
577548
var itemIndex = stagger
578549
? options.staggerIndex >= 0
579550
? options.staggerIndex
580-
: gcsLookup.count(cacheKey)
551+
: $$animateCache.count(cacheKey)
581552
: 0;
582553

583554
var isFirst = itemIndex === 0;
@@ -592,7 +563,7 @@ var $AnimateCssProvider = ['$animateProvider', /** @this */ function($animatePro
592563
blockTransitions(node, SAFE_FAST_FORWARD_DURATION_VALUE);
593564
}
594565

595-
var timings = computeTimings(node, fullClassName, cacheKey);
566+
var timings = computeTimings(node, fullClassName, cacheKey, !isStructural);
596567
var relativeDelay = timings.maxDelay;
597568
maxDelay = Math.max(relativeDelay, 0);
598569
maxDuration = timings.maxDuration;
@@ -630,6 +601,8 @@ var $AnimateCssProvider = ['$animateProvider', /** @this */ function($animatePro
630601
return closeAndReturnNoopAnimator();
631602
}
632603

604+
var activeClasses = pendClasses(preparationClasses, ACTIVE_CLASS_SUFFIX);
605+
633606
if (options.delay != null) {
634607
var delayStyle;
635608
if (typeof options.delay !== 'boolean') {
@@ -717,10 +690,13 @@ var $AnimateCssProvider = ['$animateProvider', /** @this */ function($animatePro
717690
animationClosed = true;
718691
animationPaused = false;
719692

720-
if (!options.$$skipPreparationClasses) {
693+
if (preparationClasses && !options.$$skipPreparationClasses) {
721694
$$jqLite.removeClass(element, preparationClasses);
722695
}
723-
$$jqLite.removeClass(element, activeClasses);
696+
697+
if (activeClasses) {
698+
$$jqLite.removeClass(element, activeClasses);
699+
}
724700

725701
blockKeyframeAnimations(node, false);
726702
blockTransitions(node, false);
@@ -904,9 +880,9 @@ var $AnimateCssProvider = ['$animateProvider', /** @this */ function($animatePro
904880

905881
if (flags.recalculateTimingStyles) {
906882
fullClassName = node.getAttribute('class') + ' ' + preparationClasses;
907-
cacheKey = gcsHashFn(node, fullClassName);
883+
cacheKey = $$animateCache.cacheKey(node, method, options.addClass, options.removeClass);
908884

909-
timings = computeTimings(node, fullClassName, cacheKey);
885+
timings = computeTimings(node, fullClassName, cacheKey, false);
910886
relativeDelay = timings.maxDelay;
911887
maxDelay = Math.max(relativeDelay, 0);
912888
maxDuration = timings.maxDuration;

src/ngAnimate/animateQueue.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -438,7 +438,7 @@ var $$AnimateQueueProvider = ['$animateProvider', /** @this */ function($animate
438438
if (existingAnimation.state === RUNNING_STATE) {
439439
normalizeAnimationDetails(element, newAnimation);
440440
} else {
441-
applyGeneratedPreparationClasses(element, isStructural ? event : null, options);
441+
applyGeneratedPreparationClasses($$jqLite, element, isStructural ? event : null, options);
442442

443443
event = newAnimation.event = existingAnimation.event;
444444
options = mergeAnimationDetails(element, existingAnimation, newAnimation);

0 commit comments

Comments
 (0)