Pull web-animations-js into third-party via the third_party/polymer/reproduce.sh...
[chromium-blink-merge.git] / third_party / polymer / components-chromium / core-animation / core-animation-extracted.js
blob3c6bb6911cb3058bff9a80125e47142040c355b6
2     (function() {
4       function toNumber(value, allowInfinity) {
5         return (allowInfinity && value === 'Infinity') ? Number.POSITIVE_INFINITY : Number(value);
6       };
8       Polymer('core-animation',{
9        /**
10         * Fired when the animation completes.
11         *
12         * @event core-animation-finish
13         */
15        /**
16         *
17         * Fired when the web animation object changes.
18         *
19         * @event core-animation-change
20         */
22         publish: {
24           /**
25            * One or more nodes to animate.
26            *
27            * @property target
28            * @type HTMLElement|Node|Array<HTMLElement|Node>
29            */
30           target: {value: null, reflect: true},
32           /**
33            * Animation keyframes specified as an array of dictionaries of
34            * &lt;css properties&gt;:&lt;array of values&gt; pairs. For example,
35            *
36            * @property keyframes
37            * @type Object
38            */
39           keyframes: {value: null, reflect: true},
41           /**
42            * A custom animation function. Either provide this or `keyframes`. The signature
43            * of the callback is `EffectsCallback(timeFraction, target, animation)`
44            *
45            * @property customEffect
46            * @type Function(number, Object, Object)
47            */
48           customEffect: {value: null, reflect: true},
50           /**
51            * Controls the composition behavior. If set to "replace", the effect overrides
52            * the underlying value for the target. If set the "add", the effect is added to
53            * the underlying value for the target. If set to "accumulate", the effect is
54            * accumulated to the underlying value for the target.
55            *
56            * In cases such as numbers or lengths, "add" and "accumulate" produce the same
57            * value. In list values, "add" is appending to the list, while "accumulate" is
58            * adding the individual components of the list.
59            *
60            * For example, adding `translateX(10px)` and `translateX(25px)` produces
61            * `translateX(10px) translateX(25px)` and accumulating produces `translateX(35px)`.
62            *
63            * @property composite
64            * @type "replace"|"add"|"accumulate"
65            * @default "replace"
66            */
67           composite: {value: 'replace', reflect: true},
69           /**
70            * Animation duration in milliseconds, "Infinity", or "auto". "auto" is
71            * equivalent to 0.
72            *
73            * @property duration
74            * @type number|"Infinity"
75            * @default "auto"
76            */
77           duration: {value: 'auto', reflect: true},
79           /**
80            * Controls the effect the animation has on the target when it's not playing.
81            * The possible values are "none", "forwards", "backwards", "both" or "auto".
82            *
83            * "none" means the animation has no effect when it's not playing.
84            *
85            * "forwards" applies the value at the end of the animation after it's finished.
86            *
87            * "backwards" applies the value at the start of the animation to the target
88            * before it starts playing and has no effect when the animation finishes.
89            *
90            * "both" means "forwards" and "backwards". "auto" is equivalent to "none".
91            *
92            * @property fill
93            * @type "none"|"forwards"|"backwards"|"both"|"auto"
94            * @default "auto"
95            */
96           fill: {value: 'auto', reflect: true},
98           /**
99            * A transition timing function. The values are equivalent to the CSS
100            * counterparts.
101            *
102            * @property easing
103            * @type string
104            * @default "linear"
105            */
106           easing: {value: 'linear', reflect: true},
108           /**
109            * The number of milliseconds to delay before beginning the animation.
110            *
111            * @property delay
112            * @type Number
113            * @default 0
114            */
115           delay: {value: 0, reflect: true},
117           /**
118            * The number of milliseconds to wait after the animation finishes. This is
119            * useful, for example, in an animation group to wait for some time before
120            * beginning the next item in the animation group.
121            *
122            * @property endDelay
123            * @type number
124            * @default 0
125            */
126           endDelay: {value: 0, reflect: true},
128           /**
129            * The number of iterations this animation should run for.
130            *
131            * @property iterations
132            * @type Number|'Infinity'
133            * @default 1
134            */
135           iterations: {value: 1, reflect: true},
137           /**
138            * Number of iterations into the animation in which to begin the effect.
139            * For example, setting this property to 0.5 and `iterations` to 2 will
140            * cause the animation to begin halfway through the first iteration but still
141            * run twice.
142            *
143            * @property iterationStart
144            * @type Number
145            * @default 0
146            */
147           iterationStart: {value: 0, reflect: true},
149           /**
150            * (not working in web animations polyfill---do not use)
151            *
152            * Controls the iteration composition behavior. If set to "replace", the effect for
153            * every iteration is independent of each other. If set to "accumulate", the effect
154            * for iterations of the animation will build upon the value in the previous iteration.
155            *
156            * Example:
157            *
158            *    // Moves the target 50px on the x-axis over 5 iterations.
159            *    <core-animation iterations="5" iterationComposite="accumulate">
160            *      <core-animation-keyframe>
161            *        <core-animation-prop name="transform" value="translateX(10px)"></core-animation-prop>
162            *      </core-animation-keyframe>
163            *    </core-animation>
164            *
165            * @property iterationComposite
166            * @type "replace"|"accumulate"
167            * @default false
168            */
169           iterationComposite: {value: 'replace', reflect: true},
171           /**
172            * The playback direction of the animation. "normal" plays the animation in the
173            * normal direction. "reverse" plays it in the reverse direction. "alternate"
174            * alternates the playback direction every iteration such that even iterations are
175            * played normally and odd iterations are reversed. "alternate-reverse" plays
176            * even iterations in the reverse direction and odd iterations in the normal
177            * direction.
178            *
179            * @property direction
180            * @type "normal"|"reverse"|"alternate"|"alternate-reverse"
181            * @default "normal"
182            */
183           direction: {value: 'normal', reflect: true},
185           /**
186            * A multiplier to the playback rate to the animation.
187            *
188            * @property playbackRate
189            * @type number
190            * @default 1
191            */
192           playbackRate: {value: 1, reflect: true},
194           /**
195            * If set to true, play the animation when it is created or a property is updated.
196            *
197            * @property autoplay
198            * @type boolean
199            * @default false
200            */
201           autoplay: {value: false, reflect: true}
203         },
205         animation: false,
207         observe: {
208           target: 'apply',
209           keyframes: 'apply',
210           customEffect: 'apply',
211           composite: 'apply',
212           duration: 'apply',
213           fill: 'apply',
214           easing: 'apply',
215           iterations: 'apply',
216           iterationStart: 'apply',
217           iterationComposite: 'apply',
218           delay: 'apply',
219           endDelay: 'apply',
220           direction: 'apply',
221           playbackRate: 'apply',
222           autoplay: 'apply'
223         },
225         ready: function() {
226           this.apply();
227         },
229         /**
230          * Plays the animation. If the animation is currently paused, seeks the animation
231          * to the beginning before starting playback.
232          *
233          * @method play
234          * @return AnimationPlayer The animation player.
235          */
236         play: function() {
237           this.apply();
238           if (this.animation && !this.autoplay) {
239             this.player = document.timeline.play(this.animation);
240             this.player.onfinish = this.animationFinishHandler.bind(this);
241             return this.player;
242           }
243         },
245         /**
246          * Stops the animation and clears all effects on the target.
247          *
248          * @method cancel
249          */
250         cancel: function() {
251           if (this.player) {
252             this.player.cancel();
253           }
254         },
256         /**
257          * Seeks the animation to the end.
258          *
259          * @method finish
260          */
261         finish: function() {
262           if (this.player) {
263             this.player.finish();
264           }
265         },
267         /**
268          * Pauses the animation.
269          *
270          * @method pause
271          */
272         pause: function() {
273           if (this.player) {
274             this.player.pause();
275           }
276         },
278         /**
279          * @method hasTarget
280          * @return boolean True if `target` is defined.
281          */
282         hasTarget: function() {
283           return this.target !== null;
284         },
286         /**
287          * Creates a web animations object based on this object's properties, and
288          * plays it if autoplay is true.
289          *
290          * @method apply
291          * @return Object A web animation.
292          */
293         apply: function() {
294           this.animation = this.makeAnimation();
295           if (this.autoplay && this.animation) {
296             this.play();
297           }
298           return this.animation;
299         },
301         makeSingleAnimation: function(target) {
302           // XXX(yvonne): for selecting all the animated elements.
303           target.classList.add('core-animation-target');
304           return new Animation(target, this.animationEffect, this.timingProps);
305         },
307         makeAnimation: function() {
308           if (!this.target) {
309             return null;
310           }
311           var animation;
312           if (Array.isArray(this.target)) {
313             var array = [];
314             this.target.forEach(function(t) {
315               array.push(this.makeSingleAnimation(t));
316             }.bind(this));
317             animation = new AnimationGroup(array);
318           } else {
319             animation = this.makeSingleAnimation(this.target);
320           }
321           return animation;
322         },
324         animationChanged: function() {
325           // Sending 'this' with the event so you can always get the animation object
326           // that fired the event, due to event retargetting in shadow DOM.
327           this.fire('core-animation-change', this);
328         },
330         targetChanged: function(old) {
331           if (old) {
332             old.classList.remove('core-animation-target');
333           }
334         },
336         get timingProps() {
337           var props = {};
338           var timing = {
339             delay: {isNumber: true},
340             endDelay: {isNumber: true},
341             fill: {},
342             iterationStart: {isNumber: true},
343             iterations: {isNumber: true, allowInfinity: true},
344             duration: {isNumber: true},
345             playbackRate: {isNumber: true},
346             direction: {},
347             easing: {}
348           };
349           for (t in timing) {
350             if (this[t] !== null) {
351               var name = timing[t].property || t;
352               props[name] = timing[t].isNumber && this[t] !== 'auto' ?
353                   toNumber(this[t], timing[t].allowInfinity) : this[t];
354             }
355           }
356           return props;
357         },
359         get animationEffect() {
360           var props = {};
361           var frames = [];
362           var effect;
363           if (this.keyframes) {
364             frames = this.keyframes;
365           } else if (!this.customEffect) {
366             var children = this.querySelectorAll('core-animation-keyframe');
367             if (children.length === 0 && this.shadowRoot) {
368               children = this.shadowRoot.querySelectorAll('core-animation-keyframe');
369             }
370             Array.prototype.forEach.call(children, function(c) {
371               frames.push(c.properties);
372             });
373           }
374           if (this.customEffect) {
375             effect = this.customEffect;
376           } else {
377             // effect = new KeyframeEffect(frames, this.composite);
378             effect = frames;
379           }
380           return effect;
381         },
383         animationFinishHandler: function() {
384           this.fire('core-animation-finish');
385         }
387       });
388     })();
389   ;
391     Polymer('core-animation-keyframe',{
392       publish: {
393         /**
394          * An offset from 0 to 1.
395          *
396          * @property offset
397          * @type Number
398          */
399         offset: {value: null, reflect: true}
400       },
401       get properties() {
402         var props = {};
403         var children = this.querySelectorAll('core-animation-prop');
404         Array.prototype.forEach.call(children, function(c) {
405           props[c.name] = c.value;
406         });
407         if (this.offset !== null) {
408           props.offset = this.offset;
409         }
410         return props;
411       }
412     });
413   ;
415     Polymer('core-animation-prop',{
416       publish: {
417         /**
418          * A CSS property name.
419          *
420          * @property name
421          * @type string
422          */
423         name: {value: '', reflect: true},
425         /**
426          * The value for the CSS property.
427          *
428          * @property value
429          * @type string|number
430          */
431         value: {value: '', reflect: true}
432       }
433     });
434