1
2    (function() {
3
4      var ANIMATION_GROUPS = {
5        'par': AnimationGroup,
6        'seq': AnimationSequence
7      };
8
9      Polymer('core-animation-group',{
10
11        publish: {
12          /**
13           * If target is set, any children without a target will be assigned the group's
14           * target when this property is set.
15           *
16           * @property target
17           * @type HTMLElement|Node|Array|Array<HTMLElement|Node>
18           */
19
20          /**
21           * For a `core-animation-group`, a duration of "auto" means the duration should
22           * be the specified duration of its children. If set to anything other than
23           * "auto", any children without a set duration will be assigned the group's duration.
24           *
25           * @property duration
26           * @type number
27           * @default "auto"
28           */
29          duration: {value: 'auto', reflect: true},
30
31          /**
32           * The type of the animation group. 'par' creates a parallel group and 'seq' creates
33           * a sequential group.
34           *
35           * @property type
36           * @type String
37           * @default 'par'
38           */
39          type: {value: 'par', reflect: true}
40        },
41
42        typeChanged: function() {
43          this.apply();
44        },
45
46        targetChanged: function() {
47          // Only propagate target to children animations if it's defined.
48          if (this.target) {
49            this.doOnChildren(function(c) {
50              c.target = this.target;
51            }.bind(this));
52          }
53        },
54
55        durationChanged: function() {
56          if (this.duration && this.duration !== 'auto') {
57            this.doOnChildren(function(c) {
58              // Propagate to children that is not a group and has no
59              // duration specified.
60              if (!c.type && (!c.duration || c.duration === 'auto')) {
61                c.duration = this.duration;
62              }
63            }.bind(this));
64          }
65        },
66
67        doOnChildren: function(inFn) {
68          var children = this.children;
69          if (!children.length) {
70            children = this.shadowRoot ? this.shadowRoot.childNodes : [];
71          }
72          Array.prototype.forEach.call(children, function(c) {
73            // TODO <template> in the way
74            c.apply && inFn(c);
75          }, this);
76        },
77
78        makeAnimation: function() {
79          return new ANIMATION_GROUPS[this.type](this.childAnimations, this.timingProps);
80        },
81
82        hasTarget: function() {
83          var ht = this.target !== null;
84          if (!ht) {
85            this.doOnChildren(function(c) {
86              ht = ht || c.hasTarget();
87            }.bind(this));
88          }
89          return ht;
90        },
91
92        apply: function() {
93          // Propagate target and duration to child animations first.
94          this.durationChanged();
95          this.targetChanged();
96          this.doOnChildren(function(c) {
97            c.apply();
98          });
99          return this.super();
100        },
101
102        get childAnimationElements() {
103          var list = [];
104          this.doOnChildren(function(c) {
105            if (c.makeAnimation) {
106              list.push(c);
107            }
108          });
109          return list;
110        },
111
112        get childAnimations() {
113          var list = [];
114          this.doOnChildren(function(c) {
115            if (c.animation) {
116              list.push(c.animation);
117            }
118          });
119          return list;
120        }
121      });
122
123    })();
124