angular/packages/animations/browser/src/render/animation_engine_next.ts
Matias Niemelä a5c4bb5b96 fix(animations): make sure @.disabled works in non-animation components
Note 4.3 only!

Prior to this fix when [@.disabled] was used in a component that
contained zero animation code it wouldn't register properly because the
renderer associated with that component was not an animation renderer.
This patch ensures that it gets registered even when there are no
animations set.
2017-07-19 09:50:03 -07:00

104 lines
4.0 KiB
TypeScript

/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {AnimationMetadata, AnimationPlayer, AnimationTriggerMetadata} from '@angular/animations';
import {TriggerAst} from '../dsl/animation_ast';
import {buildAnimationAst} from '../dsl/animation_ast_builder';
import {AnimationTrigger, buildTrigger} from '../dsl/animation_trigger';
import {AnimationStyleNormalizer} from '../dsl/style_normalization/animation_style_normalizer';
import {AnimationDriver} from './animation_driver';
import {parseTimelineCommand} from './shared';
import {TimelineAnimationEngine} from './timeline_animation_engine';
import {TransitionAnimationEngine} from './transition_animation_engine';
export class AnimationEngine {
private _transitionEngine: TransitionAnimationEngine;
private _timelineEngine: TimelineAnimationEngine;
private _triggerCache: {[key: string]: AnimationTrigger} = {};
// this method is designed to be overridden by the code that uses this engine
public onRemovalComplete = (element: any, context: any) => {};
constructor(driver: AnimationDriver, normalizer: AnimationStyleNormalizer) {
this._transitionEngine = new TransitionAnimationEngine(driver, normalizer);
this._timelineEngine = new TimelineAnimationEngine(driver, normalizer);
this._transitionEngine.onRemovalComplete =
(element: any, context: any) => { this.onRemovalComplete(element, context); }
}
registerTrigger(
componentId: string, namespaceId: string, hostElement: any, name: string,
metadata: AnimationTriggerMetadata): void {
const cacheKey = componentId + '-' + name;
let trigger = this._triggerCache[cacheKey];
if (!trigger) {
const errors: any[] = [];
const ast = buildAnimationAst(metadata as AnimationMetadata, errors) as TriggerAst;
if (errors.length) {
throw new Error(
`The animation trigger "${name}" has failed to build due to the following errors:\n - ${errors.join("\n - ")}`);
}
trigger = buildTrigger(name, ast);
this._triggerCache[cacheKey] = trigger;
}
this._transitionEngine.registerTrigger(namespaceId, name, trigger);
}
register(namespaceId: string, hostElement: any) {
this._transitionEngine.register(namespaceId, hostElement);
}
destroy(namespaceId: string, context: any) {
this._transitionEngine.destroy(namespaceId, context);
}
onInsert(namespaceId: string, element: any, parent: any, insertBefore: boolean): void {
this._transitionEngine.insertNode(namespaceId, element, parent, insertBefore);
}
onRemove(namespaceId: string, element: any, context: any): void {
this._transitionEngine.removeNode(namespaceId, element, context);
}
disableAnimations(element: any, disable: boolean) {
this._transitionEngine.markElementAsDisabled(element, disable);
}
process(namespaceId: string, element: any, property: string, value: any) {
if (property.charAt(0) == '@') {
const [id, action] = parseTimelineCommand(property);
const args = value as any[];
this._timelineEngine.command(id, element, action, args);
} else {
this._transitionEngine.trigger(namespaceId, element, property, value);
}
}
listen(
namespaceId: string, element: any, eventName: string, eventPhase: string,
callback: (event: any) => any): () => any {
// @@listen
if (eventName.charAt(0) == '@') {
const [id, action] = parseTimelineCommand(eventName);
return this._timelineEngine.listen(id, element, action, callback);
}
return this._transitionEngine.listen(namespaceId, element, eventName, eventPhase, callback);
}
flush(microtaskId: number = -1): void { this._transitionEngine.flush(microtaskId); }
get players(): AnimationPlayer[] {
return (this._transitionEngine.players as AnimationPlayer[])
.concat(this._timelineEngine.players as AnimationPlayer[]);
}
whenRenderingDone(): Promise<any> { return this._transitionEngine.whenRenderingDone(); }
}