| OLD | NEW |
| (Empty) |
| 1 part of angular.animate; | |
| 2 | |
| 3 /** | |
| 4 * This defines the standard set of CSS animation classes, transitions, and | |
| 5 * nomenclature that will eventually be the foundation of the AngularDart | |
| 6 * animation framework. This implementation uses the [AnimationLoop] class to | |
| 7 * queue and run CSS based transition and keyframe animations. | |
| 8 */ | |
| 9 @Injectable() | |
| 10 class CssAnimate implements Animate { | |
| 11 static const NG_ANIMATE = "ng-animate"; | |
| 12 static const NG_MOVE = "ng-move"; | |
| 13 static const NG_INSERT = "ng-enter"; | |
| 14 static const NG_REMOVE = "ng-leave"; | |
| 15 | |
| 16 static const NG_ADD_POSTFIX = "-add"; | |
| 17 static const NG_REMOVE_POSTFIX = "-remove"; | |
| 18 static const NG_ACTIVE_POSTFIX = "-active"; | |
| 19 | |
| 20 final NoOpAnimation _noOp = new NoOpAnimation(); | |
| 21 | |
| 22 final AnimationLoop _runner; | |
| 23 final AnimationOptimizer _optimizer; | |
| 24 final CssAnimationMap _animationMap; | |
| 25 | |
| 26 CssAnimate(this._runner, this._animationMap, this._optimizer); | |
| 27 | |
| 28 Animation addClass(dom.Element element, String cssClass) { | |
| 29 if (!_optimizer.shouldAnimate(element)) { | |
| 30 element.classes.add(cssClass); | |
| 31 return _noOp; | |
| 32 } | |
| 33 | |
| 34 cancelAnimation(element, "$cssClass$NG_REMOVE_POSTFIX"); | |
| 35 var event = "$cssClass$NG_ADD_POSTFIX"; | |
| 36 return animate(element, event, addAtEnd: cssClass); | |
| 37 } | |
| 38 | |
| 39 Animation removeClass(dom.Element element, String cssClass) { | |
| 40 if (!_optimizer.shouldAnimate(element)) { | |
| 41 element.classes.remove(cssClass); | |
| 42 return _noOp; | |
| 43 } | |
| 44 | |
| 45 cancelAnimation(element, "$cssClass$NG_ADD_POSTFIX"); | |
| 46 | |
| 47 var event = "$cssClass$NG_REMOVE_POSTFIX"; | |
| 48 return animate(element, event, removeAtEnd: cssClass); | |
| 49 } | |
| 50 | |
| 51 Animation insert(Iterable<dom.Node> nodes, dom.Node parent, | |
| 52 { dom.Node insertBefore }) { | |
| 53 util.domInsert(nodes, parent, insertBefore: insertBefore); | |
| 54 | |
| 55 var animations = util.getElements(nodes) | |
| 56 .where((el) =>_optimizer.shouldAnimate(el)) | |
| 57 .map((el) => animate(el, NG_INSERT)); | |
| 58 | |
| 59 return _animationFromList(animations); | |
| 60 } | |
| 61 | |
| 62 Animation remove(Iterable<dom.Node> nodes) { | |
| 63 var animations = nodes.map((node) { | |
| 64 if (node.nodeType == dom.Node.ELEMENT_NODE && | |
| 65 _optimizer.shouldAnimate(node)) { | |
| 66 return animate(node, NG_REMOVE); | |
| 67 } | |
| 68 return _noOp; | |
| 69 }); | |
| 70 | |
| 71 var result = _animationFromList(animations)..onCompleted.then((result) { | |
| 72 if (result.isCompleted) nodes.toList().forEach((n) => n.remove()); | |
| 73 }); | |
| 74 | |
| 75 return result; | |
| 76 } | |
| 77 | |
| 78 Animation move(Iterable<dom.Node> nodes, dom.Node parent, | |
| 79 { dom.Node insertBefore }) { | |
| 80 util.domMove(nodes, parent, insertBefore: insertBefore); | |
| 81 | |
| 82 var animations = util.getElements(nodes) | |
| 83 .where((el) => _optimizer.shouldAnimate(el)) | |
| 84 .map((el) => animate(el, NG_MOVE)); | |
| 85 | |
| 86 return _animationFromList(animations); | |
| 87 } | |
| 88 | |
| 89 /** | |
| 90 * Run a css animation on a element for a given css class. If the css | |
| 91 * animation already exists, the method will attempt to return the existing | |
| 92 * instance. | |
| 93 */ | |
| 94 CssAnimation animate( | |
| 95 dom.Element element, | |
| 96 String event, | |
| 97 { String addAtStart, | |
| 98 String addAtEnd, | |
| 99 String removeAtStart, | |
| 100 String removeAtEnd }) { | |
| 101 | |
| 102 var _existing = _animationMap.findExisting(element, event); | |
| 103 if (_existing != null) return _existing; | |
| 104 | |
| 105 var animation = new CssAnimation( | |
| 106 element, | |
| 107 event, | |
| 108 "$event$NG_ACTIVE_POSTFIX", | |
| 109 addAtStart: addAtStart, | |
| 110 addAtEnd: addAtEnd, | |
| 111 removeAtStart: removeAtStart, | |
| 112 removeAtEnd: removeAtEnd, | |
| 113 animationMap: _animationMap, | |
| 114 optimizer: _optimizer); | |
| 115 | |
| 116 _runner.play(animation); | |
| 117 return animation; | |
| 118 } | |
| 119 | |
| 120 /** | |
| 121 * For a given element and css event, attempt to find an existing instance | |
| 122 * of the given animation and cancel it. | |
| 123 */ | |
| 124 void cancelAnimation(dom.Element element, String event) { | |
| 125 var existing = _animationMap.findExisting(element, event); | |
| 126 | |
| 127 if (existing != null) existing.cancel(); | |
| 128 } | |
| 129 } | |
| 130 | |
| 131 /** | |
| 132 * Tracked set of currently running css animations grouped by element. | |
| 133 */ | |
| 134 @Injectable() | |
| 135 class CssAnimationMap { | |
| 136 final Map<dom.Element, Map<String, CssAnimation>> cssAnimations | |
| 137 = new Map<dom.Element, Map<String, CssAnimation>>(); | |
| 138 | |
| 139 void track(CssAnimation animation) { | |
| 140 var animations = cssAnimations.putIfAbsent(animation.element, | |
| 141 () => <String, CssAnimation>{}); | |
| 142 animations[animation.eventClass] = animation; | |
| 143 } | |
| 144 | |
| 145 void forget(CssAnimation animation) { | |
| 146 var animations = cssAnimations[animation.element]; | |
| 147 animations.remove(animation.eventClass); | |
| 148 if (animations.length == 0) cssAnimations.remove(animation.element); | |
| 149 } | |
| 150 | |
| 151 CssAnimation findExisting(dom.Element element, String event) { | |
| 152 var animations = cssAnimations[element]; | |
| 153 if (animations == null) return null; | |
| 154 return animations[event]; | |
| 155 } | |
| 156 } | |
| OLD | NEW |